題意:兩個字符串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; }
我的建議只看看個人作題思路就好,代碼就本身寫吧~我本身都看着頭大。