String Distance and Transform Process 小白詳解

題意:兩個字符串str1,str2。讓str1去匹配str2。能夠對str1增,刪,改。ios

Insert pos,value 
Delete pos 
Replace pos,value spa

輸入樣例:code

abcac
bcd
aaa
aabaaaa

輸出樣例:blog

3
1 Delete 1
2 Replace 3,d
3 Delete 4
4
1 Insert 1,a
2 Insert 2,a
3 Insert 3,b
4 Insert 7,a

方法:動態規劃ci

1.dp[i][j],i是str1的第i位,j是str2的,表示到str1[i-1],str[j-1]匹配後須要多少步字符串

2.dp[x][y]=min(dp[x-1][y]+1,dp[x][y-1]+1,dp[x-1][y-1]+(str1[i-1] 與 str2[j-1] 是否同樣,同樣就不須要操做(改),不同就須要改 ) );string

3.邊界條件:str1長度爲0時,dp[0][str2.size()] 須要str2.size() 步(增str2.size()次);it

4.遍歷順序:asc(順序)io

注意:class

1.dp[str1.size()][str2.size()];//錯誤演示:dp[len1][len2];

2.增刪改;改優於增,改優於刪。

不太友好的代碼以下:

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;

#define xx 81

int min(int x, int y, int z) {
    x = x < y ? x : y;
    return x < z ? x : z;
}

int main() {
    string str1, str2;
    int dp[xx][xx];
    bool flag[xx][xx];
    int len1, len2;

    while (cin >> str1 >> str2) {
        len1 = str1.size(), len2 = str2.size();
        //cout << len1 << "     " << len2 << endl;
        //執行flag
        for (int i = 0; i < len1; i++)
            for (int j = 0; j < len2; j++)
                flag[i][j] = str1[i] == str2[j] ? 0 : 1;
        //肯定邊界
        for (int i = 0; i < xx; ++i)dp[i][0] = dp[0][i] = i;
        //執行dp
        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + flag[i-1][j-1]);//增 刪 改
            }
        }
        //操做
        cout << dp[len1][len2] << "\n";
        for (int k = 1; k <= dp[str1.size()][str2.size()];) {
            int t;
            if (len1 == 0 && len2 != 0)t = 1;
            else if (len1 != 0 && len2 == 0)t = 2;
            else if (len1 != 0 && len2 != 0) {
                /*
                if (dp[len1][len2 - 1] == min(dp[len1 - 1][len2], dp[len1][len2 - 1], dp[len1 - 1][len2 - 1]))t = 1;//增
                else if (dp[len1 - 1][len2] == min(dp[len1 - 1][len2], dp[len1][len2 - 1], dp[len1 - 1][len2 - 1]))t = 2;//刪
                else if (dp[len1 - 1][len2 - 1] == min(dp[len1 - 1][len2], dp[len1][len2 - 1], dp[len1 - 1][len2 - 1]))t = (dp[len1 - 1][len2 - 1] == dp[len1][len2] ? 0 : 3);//是否改
                */
                //改優先與增,改優先於刪
                if (dp[len1 - 1][len2 - 1] == min(dp[len1 - 1][len2], dp[len1][len2 - 1], dp[len1 - 1][len2 - 1]))t = (dp[len1 - 1][len2 - 1] == dp[len1][len2] ? 0 : 3);//是否改
                else if (dp[len1][len2 - 1] == min(dp[len1 - 1][len2], dp[len1][len2 - 1], dp[len1 - 1][len2 - 1]))t = 1;//
                else if (dp[len1 - 1][len2] == min(dp[len1 - 1][len2], dp[len1][len2 - 1], dp[len1 - 1][len2 - 1]))t = 2;//
            }
            //cout << k << "     " << dp[str1.size()][str2.size()] << endl;
            //cout << len1 << len2 << endl;
            switch (t) {
            case 0:len1--, len2--;break;//不改
            case 1:printf("%d Insert %d,%c\n", k++, len1 + 1, str2[--len2]);break;//
            case 2:printf("%d Delete %d\n", k++, len1--);break;//
            case 3:printf("%d Replace %d,%c\n", k++, len1--, str2[--len2]);break;//
            default:break;
            }

        }
        //cout << " over " << endl;

    }
    return 0;
}

我的建議只看看個人作題思路就好,代碼就本身寫吧~我本身都看着頭大。

相關文章
相關標籤/搜索