dp[i][j]表示把前i个A串转化为前j个B串需要的最少操作。
op[i][j]表示这个当前操作是插入,删除或者替换。
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define L(t) t<<1
#define R(t) t<<1|1
#define eps 1e-7
typedef long long LL;
const int INF=1000000010;
const int maxn=1005;
const int maxm=1000005;
const int MOD=1000000007;
char s1[maxn],s2[maxn];
int la,lb;
int dp[maxn][maxn],op[maxn][maxn];
struct node
{
int ope;
int pi,pj;
node(int p,int i,int j):ope(p),pi(i),pj(j){};
};
stack<node> st;
int dsum=0;
void print(node cur)
{
if(cur.ope==1)
{
printf("DELETE %d\n",cur.pi-dsum);
dsum++;
}
if(cur.ope==2)
{
printf("INSERT %d %c\n",cur.pi-dsum+1,s2[cur.pj]);
dsum--;
}
if(cur.ope==3)
{
// if(s1[cur.pi]!=s2[cur.pj])
printf("REPLACE %d %c\n",cur.pi-dsum,s2[cur.pj]);
}
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%s",s1+1);
scanf("%s",s2+1);
la=strlen(s1+1);
lb=strlen(s2+1);
memset(dp,0x3f,sizeof(dp));
// cout<<la<<" "<<lb<<endl;
for(int i=1;i<=la;i++)
{
dp[i][0]=i;
op[i][0]=1;//delete
}
for(int i=1;i<=lb;i++)
{
dp[0][i]=i;
op[0][i]=2;//insert
}
dp[0][0]=0;
for(int i=1;i<=la;i++)
for(int j=1;j<=lb;j++)
{
if(dp[i-1][j]+1<dp[i][j])
{
dp[i][j]=dp[i-1][j]+1;
op[i][j]=1;
}
if(dp[i][j-1]+1<dp[i][j])
{
dp[i][j]=dp[i][j-1]+1;
op[i][j]=2;
}
if(dp[i-1][j-1]+(s1[i]!=s2[j])<dp[i][j])
{
dp[i][j]=dp[i-1][j-1]+(s1[i]!=s2[j]);
op[i][j]=3+(s1[i]==s2[j]);
}
}
printf("%d\n",dp[la][lb]);
while(la||lb)
{
st.push(node(op[la][lb],la,lb));
if(op[la][lb]==1)
la--;
else if(op[la][lb]==2)
lb--;
else if(op[la][lb]>=3)
{
la--;lb--;
}
}
while(!st.empty())
{
print(st.top());
st.pop();
}
return 0;
}

本文详细阐述了使用动态规划(DP)算法解决字符串匹配问题的过程,包括状态转移方程的构建、边界条件的设定以及如何通过算法实现从源字符串到目标字符串的最优转换路径。文章还介绍了如何通过DP矩阵和操作标记来记录转换过程中的具体操作类型,如插入、删除和替换,最终输出从源字符串到目标字符串所需的最少操作数及其操作序列。

被折叠的 条评论
为什么被折叠?



