C++

String Distance and Transform Process 小白详解


题意:两个字符串str1,str2。让str1去匹配str2。可以对str1增,删,改。

Insert pos,value 
Delete pos 
Replace pos,value 

输入样例:

abcac
bcd
aaa
aabaaaa

输出样例:

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

方法:动态规划

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] 是否一样,一样就不需要操作(改),不一样就需要改 ) );

3.边界条件:str1长度为0时,dp[0][str2.size()] 需要str2.size() 步(增str2.size()次);

4.遍历顺序:asc(顺序)

注意:

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;
}

个人建议只看看我的做题思路就好,代码就自己写吧~我自己都看着头大。


作者:sos3210,发布于:2020/07/27
原文:https://www.cnblogs.com/sos3210/p/13384731.html