diff --git a/139/139.md b/139/139.md new file mode 100644 index 0000000..0e30449 --- /dev/null +++ b/139/139.md @@ -0,0 +1,103 @@ +## 何も見ずに解いてみる + +最初に思い浮かんだ解法で解いてみる。DPみたいにするなら、今までの文字数すべてについて分解できるかできないかがわかっていたら、そこから最終文字までの単語がwordDictに含まれているかどうかを調べればできそう。 + +```cpp +class Solution { +public: + bool wordBreak(string s, vector& wordDict) { + unordered_set words(wordDict.begin(), wordDict.end()); + unordered_set visited; + queue index_to_check; + index_to_check.push(0); + while (!index_to_check.empty()) { + int index = index_to_check.front(); + index_to_check.pop(); + for (int i = 1; i <= s.size() - index; ++i) { + string new_word = s.substr(index, i); + if (words.contains(new_word)) { + int new_index = index + i; + if (new_index == s.size()) { + return true; + } + if (visited.contains(new_index)) { + continue; + } + visited.insert(new_index); + index_to_check.push(new_index); + } + } + } + return false; + } +}; +``` + +## 他の人のコードを見てみる + +https://github.com/Satorien/LeetCode/pull/39/files +https://github.com/ryosuketc/leetcode_arai60/pull/52/files +https://github.com/tokuhirat/LeetCode/pull/39/files +https://github.com/Ryotaro25/leetcode_first60/pull/43/files +https://github.com/frinfo702/software-engineering-association/pull/3/files +https://github.com/philip82148/leetcode-swejp/pull/8/files +https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%82%A4_(%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0) + +C++は長いコードになるとまだ読み慣れない・・・ + +wordDictの中を探す方法としては辞書順に並べた2分探索も選択肢に入りそうかも。 + +自分がstep1で書いたような、今いるところから前方向を向いてwordDictに入っててほしいwordを調べるやり方は、候補になるword全てをwordDictの中からチェックしなきゃいけない。 +それに比べると、step3のコードは分解できると分かったところから今いるところまでの部分列だけを探せばいいので多少効率的? +逆に、前方向を向いてwordDictに入ってるかチェックする場合には、目標となる文字列の後ろから始めることによってパフォーマンスが改善するかも。今いるところから分解できると分かったところまでの部分文字列を探せばいいので +(説明の助けになってるかわかりませんが下の絵みたいなことです) + +image + +あと、次のコード(最終コードで`substr`を呼び出すものを間違えて`s_view`ではなく`s`にしてしまっているものです)を動かすとエラーが出てなんでだろうと考えてたんですが、 +`words.contains(word)`を呼び出すときにはもうすでに`word`(string_view)が見ている先の文字列が無くなってるからですかね?(違ってたら教えてください) + +```cpp +class Solution { +public: + bool wordBreak(string s, vector& wordDict) { + string_view s_view(s); + unordered_set words(wordDict.begin(), wordDict.end()); + vector breakable_indexes = {0}; + for (int index = 1; index <= s.size(); ++index) { + for (int breakable_index : breakable_indexes) { + string_view word = s.substr(breakable_index, index - breakable_index); + if (words.contains(word)) { + breakable_indexes.push_back(index); + break; + } + } + } + return breakable_indexes.back() == s.size(); + } +}; +``` + +## 最終コード + +```cpp +class Solution { +public: + bool wordBreak(string s, vector& wordDict) { + string_view s_view(s); + unordered_set words(wordDict.begin(), wordDict.end()); + vector breakable_indexes = {0}; + for (int index = 1; index <= s.size(); ++index) { + for (int breakable_index : breakable_indexes) { + string_view word = s_view.substr(breakable_index, index - breakable_index); + if (words.contains(word)) { + breakable_indexes.push_back(index); + break; + } + } + } + return breakable_indexes.back() == s.size(); + } +}; +``` +