题意:
源串中的单个字符可被删除(delete);
被替换 (replace);
被复制到目标串中去(copy);
字符也可被插入(insert);
源串中的两个相邻字符可进行交换并复制到目标串中去(twiddle);
在完成其它所有操作之后,源串中余下的全部后缀就可用删至行末的操作删除(kill)。
操作delete,replace,copy,insert,twiddle和kill中每一个都有一个相联系的代价cost。
例如:
cost(delete)=3;
cost(replace)=6;
cost(copy)=5;
cost(insert)=4;
cost(twiddle)=4;
cost(kill)=被删除的串长*cost(delete)-1;
题解:
还是很容易知道这是dp的,设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为目标串匹配了前i个,源串删除了j个字符的最小价值。
讲解放在代码里好看一些…👇
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MOD = 1e9+7;
char s1[205],s2[205];
int dp[205][205];
int del,rep,cop,ins,tri;
int main(){
ios::sync_with_stdio(false);
//freopen("C:\\Users\\Administrator\\Desktop0\\in.txt",",r",stdin);
memset(dp,0x7f,sizeof(dp));
cin>>(s1+1)>>(s2+1);
dp[0][0] = 0;
cin>>del>>rep>>cop>>ins>>tri;
int len1 = strlen(s1+1),len2 = strlen(s2+1);
for(int i=1;i<=len2;i++) dp[i][0] = i*ins;//源串没有字符,只能选择添加
for(int i=1;i<=len1;i++) dp[0][i] = i*del;//目标串没有字符,只能选择把源串全部删掉
for(int i=1;i<=len2;i++){
for(int j=1;j<=len1;j++){
dp[i][j] = min(dp[i][j],dp[i][j-1]+del);//删除源串
dp[i][j] = min(dp[i][j],dp[i-1][j-1]+rep);//把源串字符删了,目标串添加一个
if(s2[i] == s1[j]) dp[i][j] = min(dp[i][j],dp[i-1][j-1]+cop);
//如果相等才能进行copy操作,也是相当于删一个源串字符,加一个目标串字符
dp[i][j] = min(dp[i][j],dp[i-1][j]+ins);//给目标串加一个字符
if(i-1>=1 && j-1>=1 && s2[i-1]==s1[j] && s2[i]==s1[j-1])
dp[i][j] = min(dp[i][j],dp[i-2][j-2]+tri);
//把源串的两个字符反转后放入目标串
//判断一下反转以后是否一样就好
}
}
int res = 0x7ffffff;
for(int i=1;i<len1;i++)
res = min(res,dp[len2][i]+(len1-i)*del-1);//最后要把源串字符全删
res = min(res,dp[len2][len1]);
cout<<res<<endl;
}