1. 程式人生 > 其它 >C++進階-3-4stack容器、queue容器

C++進階-3-4stack容器、queue容器

題目連結
思考:剛開始想的時候想成了區間dp,思考相同長度下不同位置的字串的匹配,大概的想法是用\(dp[len][i][j]\)來表示長度為len的A串從i開始的子串變成B串從位置j開始所需要的最小代價,後面發現運算元有三種,很難用區間的方式來維護,畢竟修改完全可以不在兩端,而且複雜度也是在\(O(10^8)\)不可能接受,所以作罷。
正解:用\(dp[i][j]\)表示A從\([1...i]\)的子串變成B從\([1...j]\)所需要的最小代價,分析三種運算元

  • 在A的末尾增加一個元素,此時代價為\(dp[i][j-1]+1\)
  • 在B的末尾增加一個元素,此時代價為\(dp[i-1][j]+1\)
  • 將A的末尾元素進行修改,如果不用修改,也就是\(A_i= B_j\)時,此時A的末尾元素不同進行修改得
\[dp[i][j]=\left\{\begin{array}{rcl} dp[i-1][j-1] &{A_i=B_j}\\ dp[i-1][j-1]+1 &{A_i \neq B_j}\end{array}\right. \]

初始狀態

\[ dp[i][j]= \begin{cases} dp[0][j]=j\\ dp[i][0]=i \end{cases} \]

為什麼從左到右推進是可以的呢,首先我們可以想象一個位置\(A_i\)假設它應該匹配上的是一個後面的\(B_j\)

,那麼它只要繼承處於i之前的\(dp[j-1]\)的值就行了,所以前段對後段沒有影響

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n=word1.size(),m=word2.size();
        int dp[n+1][m+1];
        memset(dp,0,sizeof dp);
        for(int i=0;i<=n;i++) dp[i][0]=i;
        for(int j=0;j<=m;j++) dp[0][j]=j;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int l=dp[i][j-1]+1;  //這裡表示A+1
                int r=dp[i-1][j]+1;  //這裡表示B+1;
                int c=dp[i-1][j-1]+(word1[i-1]!=word2[j-1]);
                dp[i][j]=min(l,min(r,c));
            }
        }
        return dp[n][m];
    }
};