-
Notifications
You must be signed in to change notification settings - Fork 0
139. Word Break #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
139. Word Break #43
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| string_view word = s; | ||
| set<string_view> word_dict(wordDict.begin(), wordDict.end()); | ||
| queue<int> dividing_positions; | ||
| dividing_positions.push(0); | ||
| vector<bool> visited(s.size(), false); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. vector は特殊化されており、速度がやや遅くなる可能性があります。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモリの効率化を行っているから[]の場合、インデックスでアクセスする場合に遅い場合があるのですね。。。 vectorに置き換えてみました。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. visited という名前は、グラフ等で探索済みのノードを表すのであれば自然だと思うのですが、今回のように、すでに分割地点として調べたかどうかを表すのには不適切だと感じました。あまりいい変数名が思いつかないのですが、分割済みである divided や、処理済みである proceeded あたりはいかがでしょうか? |
||
|
|
||
| while (!dividing_positions.empty()) { | ||
| int start_position = dividing_positions.front(); | ||
| dividing_positions.pop(); | ||
|
|
||
| if (start_position == word.size()) { | ||
| return true; | ||
| } | ||
|
|
||
| for (int end_position = start_position + 1; end_position <= word.size(); end_position++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 文字列の長さの最大値で打ち切ったほうが、計算量が落ち、速くなると思います。 |
||
| if (visited[end_position]) { | ||
| continue; | ||
| } | ||
| if (word_dict.contains(word.substr(start_position, end_position - start_position))) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 文字列のコピーを避けるため、
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| dividing_positions.push(end_position); | ||
| visited[end_position] = true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string str, vector<string>& wordDict) { | ||
| set<string_view> word_dict(wordDict.begin(), wordDict.end()); | ||
| queue<int> dividing_positions; | ||
| dividing_positions.push(0); | ||
| // 分割地点として処理済みか | ||
| vector<char> proceeded(str.size() + 1, FALSE); | ||
|
|
||
| while (!dividing_positions.empty()) { | ||
| int start_position = dividing_positions.front(); | ||
| dividing_positions.pop(); | ||
|
|
||
| if (start_position == str.size()) { | ||
| return true; | ||
| } | ||
| // 文字列の長さの最大値で打ち切ったほうが、計算量が落ち、速くなると思います。 | ||
| for (int end_position = start_position + 1; end_position <= str.size(); end_position++) { | ||
| if (proceeded[end_position]) { | ||
| continue; | ||
| } | ||
| // begin() end()はそれぞれイテレーター | ||
| if (word_dict.contains(string_view(str.begin() + start_position, str.begin() + end_position))) { | ||
| dividing_positions.push(end_position); | ||
| proceeded[end_position] = TRUE; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| private: | ||
| static constexpr char TRUE = 1; | ||
| static constexpr char FALSE = 0; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| map<string_view, bool> word_to_validity; | ||
| return CheckWordBreak(s, wordDict, word_to_validity); | ||
| } | ||
|
|
||
| private: | ||
| bool CheckWordBreak(const string_view& target, const vector<string>& word_dict, | ||
| map<string_view, bool>& word_to_validity) { | ||
| if (word_to_validity.contains(target)) { | ||
| return word_to_validity[target]; | ||
| } | ||
|
|
||
| if (target.empty()) { | ||
| return true; | ||
| } | ||
|
|
||
| for (const auto& word : word_dict) { | ||
| // targetがwordから始まっているかどうかをチェック | ||
| if (target.starts_with(word)) { | ||
| string_view remaining = target.substr(word.size()); | ||
| if (CheckWordBreak(remaining, word_dict, word_to_validity)) { | ||
| word_to_validity[target] = true; | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| word_to_validity[target] = false; | ||
| return false; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string str, vector<string>& wordDict) { | ||
| set<string_view> word_dict(wordDict.begin(), wordDict.end()); | ||
| // 分割地点として処理済みか | ||
| vector<char> proceeded(str.size() + 1, FALSE); | ||
| proceeded[0] = TRUE; | ||
|
|
||
| for (int start_position = 0; start_position < str.size(); start_position++) { | ||
| if (!proceeded[start_position]) { | ||
| continue; | ||
| } | ||
|
|
||
| for (int end_position = start_position + 1; end_position <= str.size(); end_position++) { | ||
| if (proceeded[end_position]) { | ||
| continue; | ||
| } | ||
|
|
||
| if (word_dict.contains(string_view(str.begin() + start_position, str.begin() + end_position))) { | ||
| proceeded[end_position] = TRUE; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return proceeded[str.size()] == TRUE; | ||
| } | ||
|
|
||
| private: | ||
| static constexpr char TRUE = 1; | ||
| static constexpr char FALSE = 0; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| ## ステップ1 | ||
| 与えられた文字列を分割しながら、wordDict内に存在するのかチェックする | ||
| wordDictはvectorからsetに入れ直してcontainsを使いたい | ||
|
|
||
| ある地点で分割して、その地点から左側と右側に分ける | ||
| 左側が辞書内に存在していれば右側をチェック。 | ||
| 右側に対して、ある地点で分割をして左側と右側に分け上記の作業をくりかえる | ||
|
|
||
| 時間計算量O(n^2) <-自信ないので間違っていたら指摘お願いいたします | ||
| contains関数の計算量はlog n | ||
| 再帰とforループ部分はn(n+1) / 2で省略するとn^2 | ||
|
|
||
| 空間計算量 | ||
| O(n) | ||
|
|
||
| ## ステップ2 | ||
| ・substr() によって string のコピーが作られるのを避ける | ||
| string_viewが使えそう。string_viewのsubstrの計算量はO(1) | ||
| https://www.modernescpp.com/index.php/c-17-avoid-copying-with-std-string-view/ | ||
| https://en.cppreference.com/w/cpp/string/basic_string_view | ||
|
|
||
| 早いからといって毎回string_viewを使うのではなく破壊的(恒久的)な変更を行いたい場合はstringを使う | ||
| 今回は単にwordDict内に存在するかチェックしたいだけなのでコピーの発生しないstring_viewを使う | ||
| https://medium.com/@chittaranjansethi/exploring-the-differences-std-string-vs-std-string-view-d1c7015162f0 | ||
|
|
||
| ## ステップ3 | ||
| **3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** | ||
|
|
||
| ## 他の方の解法 | ||
| Auxって言葉知らなかった Auxiliary(補助) | ||
| https://github.com/philip82148/leetcode-arai60/pull/8 | ||
| こちらの方は深さ優先探索を用いている。 | ||
| 幅優先探索で解くことができる。またTrieというものがある | ||
| https://github.com/Yoshiki-Iwasa/Arai60/pull/67/commits/3bd8c415249792da181d1351a108f3208c62ffce | ||
| https://github.com/fhiyo/leetcode/pull/40 | ||
| https://github.com/sakupan102/arai60-practice/pull/40 | ||
| https://github.com/SuperHotDogCat/coding-interview/pull/23 | ||
|
|
||
| ## 他の解法など | ||
| 幅優先探索をbfs.cppに実装 | ||
| startとendの文字を分割する情報を持っておく。 | ||
| 開始位置を0から初めて終了地点を動かしながら探索を行う。分割できる点があれば、それを次の開始位置として同様に探索する | ||
|
|
||
| 深さ優先探索をdfs.cppに実装 | ||
| starts_withがc++のstring_viewにも存在していた | ||
|
|
||
| Trieはtrie.cppに実装(写経) | ||
| Trie | ||
| https://en.wikipedia.org/wiki/Trie | ||
|
|
||
| Trieの練習問題は下記(どこかでやってみる) | ||
| https://leetcode.com/problems/implement-trie-prefix-tree/editorial/ | ||
|
|
||
| >vector は bool 型に対して特殊化されている。 | ||
| https://cpprefjp.github.io/reference/vector/vector.html | ||
| >配列のように連続して格納されているとは限らない | ||
|
|
||
| これが遅くなる原因か | ||
| https://zenn.dev/stmo/articles/d622a40b31fbee |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| set<string> word_dict(wordDict.begin(), wordDict.end()); | ||
| map<string, bool> word_to_validity; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. コメントでこのmap部分の定義の意図を書いておいてはいかがでしょうか?一度解いた身なので察しはつきますが、この時点では何をするためのものかわからず、読み進めながら何度かこちらに目を移し役割を確認してしまったので
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @frinfo702 step4.cpp |
||
|
|
||
| return CheckWordBreak(s, word_dict, word_to_validity); | ||
| } | ||
|
|
||
| private: | ||
| bool CheckWordBreak(const string& word, const set<string>& word_dict, map<string, bool>& word_to_validity) { | ||
| if (word_dict.contains(word)) { | ||
| return true; | ||
| } | ||
|
|
||
| if (word_to_validity.contains(word)) { | ||
| return word_to_validity[word]; | ||
| } | ||
|
|
||
| for (int i = 0; i < word.size(); i++) { | ||
| string left_side_word = word.substr(0, i + 1); | ||
|
|
||
| if (word_dict.contains(left_side_word)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここ、 if (!word_dict.contains(left_side_word)) {
continue;
}と書くと深いネストを一段改善できると思います |
||
| string right_side_word = word.substr(i + 1); | ||
| bool rest_word_validity = CheckWordBreak(right_side_word, word_dict, word_to_validity); | ||
| if (rest_word_validity) { | ||
| word_to_validity[word] = true; | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| word_to_validity[word] = false; | ||
| return false; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| set<string_view> word_dict(wordDict.begin(), wordDict.end()); | ||
| map<string_view, bool> word_to_validity; | ||
|
|
||
| return CheckWordBreakable(s, word_dict, word_to_validity); | ||
| } | ||
|
|
||
| private: | ||
| bool CheckWordBreakable(string_view word, const set<string_view>& word_dict, | ||
| map<string_view, bool>& word_to_validity) { | ||
| if (word_dict.contains(word)) { | ||
| return true; | ||
| } | ||
|
|
||
| if (word_to_validity.contains(word)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これはある種のキャッシュ のつもりで足してあると思うのですが、実際に使われる場合は基本ないように思います。合ってますでしょうか。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. あ、誤読ですね。これ false の場合使われていますね。 |
||
| return word_to_validity[word]; | ||
| } | ||
|
|
||
| for (int i = 0; i < word.size(); i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここ、word_dict 側で調べるのも手で、
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. word_dict側で調べる方式でstep4に追加しました。 |
||
| string_view left_side_word = word.substr(0, i + 1); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. こちら、wordがstring_viewなので動いていますが、wordがstringだった場合動かなくなります。 auto left_side_word_str = word.substr(0, i + 1);
string_view left_side_word = left_side_word_str;どうしてか説明できますでしょうか…?(C++って難しいですね) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philip82148 さん
私も守りきれているわけではないですが、レビューで疑問文を使うパターンはあまり多くなく、これはそのパターンから外れているように思います。通常は、提案と意図の確認ですね。
この2つは自分が知りようがないので聞いています。自分が知っているならば、書いてしまったほうがコミュニケーションコストが低いですからね。 ここの場は、「ソフトウェアエンジニアの入口レベルに到達するための訓練」という側面(もう一つの目的)もあるので、面接の情報提供、言葉使いや理解の修正が行われていることもあります。 ただ、この疑問文は「私の知っている正解を述べられるか」で疑問文を使う場面ではありません。 そういうわけで、この場合は「このように書いた場合はこの理由で動きません。(あれば)信頼できるソースへのポインターはこれです。」とまで書いてください。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda 承知しました! 元のコードが悪い訳ではありませんが、
string_view left_side_word = word_str.substr(0, i + 1);だと、 auto left_side_word_str = word.substr(0, i + 1);
string_view left_side_word = left_side_word_str;なので、 ※文字列データ本体=charの配列 ※ちなみに僕は一瞬元のコードを見てびっくりしてしまった(なんでこれ動いてるんだ?→ああ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 後ついでに There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philip82148 良くなったと思います。ありがとうございます。 そうですね。簡単にまとめます。 string_view left_side_word = word.substr(0, i + 1);の行を見たときに、word が string だとすると、これは一時オブジェクトを返し、left_side_word は生存期間が終了している string を指していることになりますね。 こういうとき、たとえば、「substr が string を返すかと思い生存期間の問題があるように勘違いした。一回 auto で受けたら勘違いしないのでは。」というのは、よりよいコードの提案(コードレビューの類型)として成立していますね。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. string_view は C++17 からなのであまり馴染がない人は多いでしょう。(私は昔、StringPiece という似たような非標準ライブラリーを使っていましたので馴染みがないです。) 提案自体へのコメントとしては、
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philip82148
この理解でした。今回はコピーを作って、コピー文字列に対して何かしたい、返却したいといった問題ではなかったのでstring_viewを使うことにしました。
これは確かにその通りでautoだとstringなのかstring_viewなのかとなりますね。誤解のないようなコードの書き方を心がけたいと思います🙇♂️
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda レビューありがとうございます。
自分もこの問題を通してstring_viewを知りました。string_viewがどういったものなのかコード内にコメントで書いておくべきでしょうか? まだGitに上げていないのですが下記のようなコメントを追記する予定です。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. いや、それは不要でしょう。それをするとほとんどすべての関数呼び出しにその粒度でコメントをつけることになりますね。 読む人が、「適切なドキュメントに当たることができる人物である」ことは仮定して書いていいです。これは知識を仮定しているというよりは「調べる能力」を仮定しています。 |
||
|
|
||
| if (word_dict.contains(left_side_word)) { | ||
| string_view right_side_word = word.substr(i + 1); | ||
| if (CheckWordBreakable(right_side_word, word_dict, word_to_validity)) { | ||
| word_to_validity[word] = true; | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| word_to_validity[word] = false; | ||
| return false; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| set<string_view> word_dict(wordDict.begin(), wordDict.end()); | ||
| map<string_view, bool> word_to_validity; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. validity という単語が何を表そうとしているのか、直感的ではないように感じました。また、 word とありますが、実際には複数の word が結合されている場合もあると思いました。 substring_to_breakable はいかがでしょうか?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nodchip |
||
|
|
||
| return CheckWordBreakable(s, word_dict, word_to_validity); | ||
| } | ||
|
|
||
| private: | ||
| bool CheckWordBreakable(string_view word, const set<string_view>& word_dict, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. string_view word の word が単語一つではなくて結合しているかを知りたいものなのが結構意外感があります。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda いい単語が出てこなかったので単純にstrとしました。 |
||
| map<string_view, bool>& word_to_validity) { | ||
| if (word_dict.contains(word)) { | ||
| return true; | ||
| } | ||
|
|
||
| if (word_to_validity.contains(word)) { | ||
| return word_to_validity[word]; | ||
| } | ||
|
|
||
| for (int i = 0; i < word.size(); i++) { | ||
| auto left_word = word.substr(0, i); | ||
|
|
||
| if (word_dict.contains(left_word)) { | ||
| auto right_word = word.substr(i + 1); | ||
| if (CheckWordBreakable(right_word, word_dict, word_to_validity)) { | ||
| word_to_validity[word] = true; | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| word_to_validity[word] = false; | ||
| return false; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string str, vector<string>& wordDict) { | ||
| set<string_view> word_dict(wordDict.begin(), wordDict.end()); | ||
| // 切り出されたstringが有効なのか関数の中で記録する | ||
| map<string_view, bool> substring_to_breakable; | ||
| return CheckWordBreakable(str, word_dict, substring_to_breakable); | ||
| } | ||
|
|
||
| private: | ||
| // string_viewのstrはデータを持っていない | ||
| // 元の文字列データ(ここではwordBreak関数のstring str)へのポインターを管理している | ||
| // コピーを発生させないため | ||
| bool CheckWordBreakable(string_view str, const set<string_view>& word_dict, | ||
| map<string_view, bool>& substring_to_breakable) { | ||
| if (word_dict.contains(str)) { | ||
| return true; | ||
| } | ||
|
|
||
| if (substring_to_breakable.contains(str)) { | ||
| return substring_to_breakable[str]; | ||
| } | ||
|
|
||
| for (const auto& word : word_dict) { | ||
| if (!str.starts_with(word)) { | ||
| continue; | ||
| } | ||
| string_view remain = str.substr(word.size()); | ||
| if (CheckWordBreakable(remain, word_dict, substring_to_breakable)) { | ||
| substring_to_breakable[str] = true; | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| substring_to_breakable[str] = false; | ||
| return false; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| TrieNode* root = new TrieNode(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これ、new したのを delete していないのでメモリーリークしています。 また、できれば Trie の構築はメンバ関数にするときれいでしょう。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. あ、単に |
||
| for (auto word : wordDict) { | ||
| TrieNode* node = root; | ||
| for (char letter : word) { | ||
| if (!node->children.contains(letter)) { | ||
| node->children[letter] = new TrieNode(); | ||
| } | ||
| node = node->children[letter]; | ||
| } | ||
| node->is_word = true; | ||
| } | ||
|
|
||
| vector<bool> is_segmented(s.size()); | ||
| for (int start = 0; start < s.size(); start++) { | ||
| if (start == 0 || is_segmented[start - 1]) { | ||
| TrieNode* node = root; | ||
| for (int end = start; end < s.size(); end++) { | ||
| char letter = s[end]; | ||
| if (!node->children.contains(letter)) { | ||
| break; | ||
| } | ||
|
|
||
| node = node->children[letter]; | ||
| if (node->is_word) { | ||
| is_segmented[end] = true; | ||
| } | ||
| } | ||
|
Comment on lines
+19
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここもメンバ関数にしてしまってもいいかもしれません。 |
||
| } | ||
| } | ||
| return is_segmented.back(); | ||
| } | ||
|
|
||
| private: | ||
| struct TrieNode { | ||
| bool is_word; | ||
| map<char, TrieNode*> children; | ||
| TrieNode() : is_word(false), children(map<char, TrieNode*>()){} | ||
| }; | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
queue<int>を使って、分割地点の候補を管理するより、 start_position を 0 から word.size() - 1 まで回したほうがシンプルだと思いました。ただし、 start_position が分割の開始地点の候補でないことを確認するため、をどこかに入れることになると思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nodchip
for.cppとして新たにファイルを追加しました。