-
Notifications
You must be signed in to change notification settings - Fork 0
139. Word Break #39
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 #39
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,103 @@ | ||
| ## 何も見ずに解いてみる | ||
|
|
||
| 最初に思い浮かんだ解法で解いてみる。DPみたいにするなら、今までの文字数すべてについて分解できるかできないかがわかっていたら、そこから最終文字までの単語がwordDictに含まれているかどうかを調べればできそう。 | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| unordered_set<string> words(wordDict.begin(), wordDict.end()); | ||
| unordered_set<int> visited; | ||
| queue<int> 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) { | ||
|
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. ここの i は word_length もしくは sub_str_length かなと思いました。
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. たしかにそちらのほうがだいぶ分かりやすくなりますね! |
||
| 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に入ってるかチェックする場合には、目標となる文字列の後ろから始めることによってパフォーマンスが改善するかも。今いるところから分解できると分かったところまでの部分文字列を探せばいいので | ||
| (説明の助けになってるかわかりませんが下の絵みたいなことです) | ||
|
|
||
| <img width="1593" height="854" alt="image" src="https://github.com/user-attachments/assets/1167f5d0-9d75-40a8-bcca-f06304e828ac" /> | ||
|
|
||
| あと、次のコード(最終コードで`substr`を呼び出すものを間違えて`s_view`ではなく`s`にしてしまっているものです)を動かすとエラーが出てなんでだろうと考えてたんですが、 | ||
| `words.contains(word)`を呼び出すときにはもうすでに`word`(string_view)が見ている先の文字列が無くなってるからですかね?(違ってたら教えてください) | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| bool wordBreak(string s, vector<string>& wordDict) { | ||
| string_view s_view(s); | ||
| unordered_set<string_view> words(wordDict.begin(), wordDict.end()); | ||
| vector<int> 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<string>& wordDict) { | ||
| string_view s_view(s); | ||
| unordered_set<string_view> words(wordDict.begin(), wordDict.end()); | ||
| vector<int> 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; | ||
| } | ||
|
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 (int end = 1; end <= s.size(); ++end) {
for (int start : breakable_indexes) {
string_view sub_str = s_view.substr(start, end - start);
if (words.contains(sub_str)) { |
||
| } | ||
| } | ||
| return breakable_indexes.back() == s.size(); | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
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.
型で分かると言えば分かるのですが、
visited_indicesの命名とかの方がよりわかりやすいと思います。