Skip to content

139. Word Break#37

Open
hemispherium wants to merge 2 commits into
mainfrom
0139-word-break
Open

139. Word Break#37
hemispherium wants to merge 2 commits into
mainfrom
0139-word-break

Conversation

@hemispherium
Copy link
Copy Markdown
Owner

@hemispherium hemispherium self-assigned this Apr 30, 2026
Comment thread 0139-word-break/step1.cpp
class Solution {
public:
bool FindWordRecursively(string s, vector<string>& wordDict, unordered_map<string, bool>& memo) {
if (s.size() == 0) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (s.empty()) {

のほうがシンプルだと思います。
https://cpprefjp.github.io/reference/string/basic_string/empty.html

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。そちらの方がシンプルそうです。

Comment thread 0139-word-break/step1.cpp
return true;
}

if (memo.count(s)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++20 以降なら std::unordered_map::contains() を使うことをお勧めいたします。
https://cpprefjp.github.io/reference/unordered_map/unordered_map/contains.html

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。こちらのメンバ関数は知りませんでした。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらですが過去のPRで複数回同じ指摘があったようです。同じ指摘を受けないように、次回以降のPRで反映させるとより効果的な学習になると思います。

#16 (comment)
#3 (comment)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

失礼しました。気をつけます。

Comment thread 0139-word-break/step1.cpp
@@ -0,0 +1,28 @@
class Solution {
public:
bool FindWordRecursively(string s, vector<string>& wordDict, unordered_map<string, bool>& memo) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memo という変数名に、あまり情報がないように思いました。ある接頭辞が breakable かどうかを表す map ですので、 prefix_to_breakable はいかがでしょうか?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。そちらの名前にしようと思います。

Comment thread 0139-word-break/step1.cpp
@@ -0,0 +1,28 @@
class Solution {
public:
bool FindWordRecursively(string s, vector<string>& wordDict, unordered_map<string, bool>& memo) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string を値渡しすると、毎回コピーが発生します。 const 参照で渡すことをお勧めいたします。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

承知しました!

Comment thread 0139-word-break/step1.cpp
@@ -0,0 +1,28 @@
class Solution {
public:
bool FindWordRecursively(string s, vector<string>& wordDict, unordered_map<string, bool>& memo) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unordered_map<string, bool> より、 std::vector として、何文字目以降の接頭辞は breakable かを保持するようにしたほうが、ハッシュの計算が省略でき、軽くなると思います。未調査・breakable・unbreakable の 3 つの値を格納することになると思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます!こちらの実装alternative-solution.cppで追加してみました。

Comment thread 0139-word-break/memo.md
@@ -0,0 +1,11 @@
### step1

再帰的に辞書からワードを探す形で実装。TLEしたのでメモ化する部分だけChatGPTに書いてもらった。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DPでも書けますか?

Comment thread 0139-word-break/step3.cpp
@@ -0,0 +1,27 @@
class Solution {
public:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

アクセス修飾子を意識して使っていますか?このコードでは、どう変更するのが適切そうでしょうか?

参考:#23 (comment)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あまり意識していませんでした。このコードでは再帰関数は公開しなくていいと思うのでprivateにするのがよいでしょうか?

class Solution {
private:
    bool FindWordRecursively(string s, const vector<string>& wordDict, unordered_map<string, bool>& memo) {
        if (s.size() == 0) {
            return true;
        }

        if (memo.count(s)) {
            return memo[s];
        }

        for (int i = 0; i < wordDict.size(); i++) {
            if (s.starts_with(wordDict[i])) {
                if (FindWordRecursively(s.substr(wordDict[i].size()), wordDict, memo)) {
                    return memo[s] = true;
                }
            }
        }
        return memo[s] = false;
    }

public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_map<string, bool> memo;
        return FindWordRecursively(s, wordDict, memo);
    }
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

はい、そうですね。

Comment thread 0139-word-break/step1.cpp
return memo[s];
}

int size = wordDict.size();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wordDict.size()のままで良いと思います.
sizeは1箇所しか用いず,また可読性の面でも大差ないと思うので.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですね、特に変数化しなくてよかったかもしれないです。

Comment thread 0139-word-break/step1.cpp
int size = wordDict.size();
for (int i = 0; i < size; i++) {
if (s.starts_with(wordDict[i])) {
if (FindWordRecursively(s.substr(wordDict[i].size()), wordDict, memo)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string型に対するsubstr関数は都度コピーを生成することになり遅いので,string_viewに変換して扱ってはいかがでしょうか.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます!string_viewは知りませんでした。

Comment thread 0139-word-break/step1.cpp
Comment on lines +13 to +19
for (int i = 0; i < size; i++) {
if (s.starts_with(wordDict[i])) {
if (FindWordRecursively(s.substr(wordDict[i].size()), wordDict, memo)) {
return memo[s] = true;
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

実際には最悪計算量よりも平均的な計算量のほうが重要でしょうが,今回はそれがわからないので最悪計算量で考えると,今回のケースでは

  • wordDictのサイズが最大で2000
  • sのサイズは最大20

ですからwordDictを操作するよりもwordDictをsetかunordered_setに変換してsの部分文字列を操作する方が最悪計算量が小さく抑えられます.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants