【動的プログラミングを学ぶ】文字列内の唯一の部分文字列を囲む (25)

目次

動的プログラミングを学ぶにはどうすればよいですか?

1. 質問分析

2. アルゴリズム原理

1.ステータス表示

2. 状態遷移方程式

3. 初期化

4. フォームに記入する順序

5. 戻り値

3. コードの書き方

最後に次のように書きます。


動的プログラミングを学ぶにはどうすればよいですか?

動的プログラミングの学習はもちろん、アルゴリズムの学習にも近道はありません。

私と一緒に動的計画アルゴリズムの質問を解決し、動的計画を一緒に学びましょう!

1. 質問分析

質問リンク: 467. 文字列内の唯一の部分文字列を囲む - LeetCode 

この問題も分かりやすく、基本的には一度読めば理解できるので、例を挙げて見てください。

Base には空ではない異なる部分文字列が何個表示されますか? Base は a ~ za ~ z の無限サイクルです。

2. アルゴリズム原理

1.ステータス表示

dp[ i ] は、位置 i で終わるすべての部分文字列のうち、base に出現した個数を表します。

2. 状態遷移方程式

これは次の 2 つの状況に分類できます。

長さが 1 の場合、dp[i] = 1

長さが 1 より大きい場合、i 位置が前の位置と結合されていることが証明されます。

s[ i - 1 ] + 1 == s[ i ] || ( s[ i - 1 ] == 'z' && s[ i ] == 'a' ),dp[ i ] = dp[ i - 1 ]

(以前と同じくらい多くの状況が今も存在します)

求められるのはすべての状況の合計であるため、状態遷移方程式は次のようになります。

dp[ i ] = 1 + s[ i - 1 ] + 1 == s[ i ] || ( s[ i - 1 ] == 'z' && s[ i ] == 'a' ) ? dp[ i ] = dp[ i - 1 ] : 0

3. 初期化

各文字が出現する必要があるため、配列を直接 1 に初期化できます。

このようにして、状態遷移方程式では余分な 1 を追加する必要がありません。

4. フォームに記入する順序

左から右へ。

5. 戻り値

文字は繰り返される可能性があるため、すべての要素の合計を直接返すことはできません。

では、どうやって重みを取り除けばいいのでしょうか?

同じ文字で終わる dp 値の場合は、最大のものに進むことができます。                

サイズ 26 の配列を作成し、対応する文字の末尾に最大 dp 値を格納します。

最後に、合計を配列で返します。

3. コードの書き方

class Solution {
public:
    int findSubstringInWraproundString(string s) {
        int n = s.size();
        vector<int> dp(n, 1);
        for(int i = 1; i < n; i++) {
            if(s[i - 1] + 1 == s[i] || (s[i - 1] == 'z' && s[i] == 'a'))
                dp[i] += dp[i - 1];
        }

        int hash[26] = { 0 };
        for(int i = 0; i < n; i++) {
            hash[s[i] - 'a'] = max(hash[s[i] - 'a'], dp[i]);
        }

        int sum = 0;
        for(auto e : hash) sum += e;
        
        return sum;
    }
};

最後に次のように書きます。

以上がこの記事の内容です、読んでいただきありがとうございます。

何かを得たと感じたら、ブロガーに「いいね! 」を与えることができます。

記事の内容に漏れや間違いがある場合は、ブロガーにプライベートメッセージを送信するか、コメント欄で指摘してください〜

おすすめ

転載: blog.csdn.net/Locky136/article/details/131972044