题目描述
一种EDIT字母编辑器,它的功能是可以通过不同的变换操作可以把一个源串X [l..m]变换为新的目标串y[1..n]。EDIT提供的变换操作有:
源串中的单个字符可被删除(delete);
被替换 (replace);
被复制到目标串中去(copy);
字符也可被插入(insert);
源串中的两个相邻字符可进行交换并复制到目标串中去(twiddle);
在完成其它所有操作之后,源串中余下的全部后缀就可用删至行末的操作删除(kill)。
例如,将源"algorithm"转换成目标串"altruistic"的一种方法是采取下面的操作序列:
要达到这个结果还可能有其它一些操作序列。
操作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;
一个给定的操作序列的代价为序列中各操作代价之和。 例如上述操作序列的代价为
3*cost(copy)+2*cost(replace)+cost(delete)+3*cost(insert) + cost(twiddle) +cost(kill)
=3*5+2*6+3+3*4+4+1*3-1=48
编程任务:
给定两个序列x[1..m],y[1..n]和一些操作代价集合,X到Y的最短距离为将X转化为Y的最小的转换序列的代价。请给出一个算法来找出x[1..m]至y[1..n]的最短距离。
输入格式
第一行:源序列x[1..m]。(m<200)
第二行:目标序列y[1..n]。(n<200)
第三行:5个正整数(<100):分别是:delete 、replace 、copy、 insert、 twiddle的代价。
输出格式
X到Y的最短距离(最小代价和)。
输入输出样例
algorithm
altruistic
3 6 5 4 4
48
【解题思路】
关于这种序列匹配的问题,思路都是一样的。
设f[i][j]表示目标串已经完成了前i位,初始串已经删除了j位。
边界:
f[0][j]=cost(delete)*j(因为目标串一位都没有,所以初始串只能删)
f[i][0]=cost(insert)*i(因为初始串一位也没动过,所以只能往目标串里添加)
对于每种操作:(设目标串为s2,初始串s1)
delete->f[i][j]=min(f[i][j],f[i][j-1]+cost(delete))
replace->f[i][j]=min(f[i][j],f[i-1][j-1]+cost(replace)) copy->f[i][j]=min(f[i][j],f[i-1][j-1]+cost(copy))(s2[i]==s1[j]) insert->f[i][j]=min(f[i][j],f[i-1][j]+cost(insert)) twiddle->f[i][j]=min(f[i][j],f[i-2][j-1]+cost(triddle))(s2[i]==s1[j-1]&&s2[i-1]==s1[j])
然后转移就好了,时间复杂度O(len(s1)*len(s2)) 最后枚举f[len(s2]j,把答案加上(len(s1)-j)*del-1;
然后和f[len(s2)][len(s1)]比较,所有的值里面取最小值。
【code】
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 using namespace std;
5 int cop,tri,del,ins,rep;
6 char s1[1001],s2[1001];
7 int f[202][202];
8 int ans;
9 inline int min(int a,int b)
10 {
11 return a<b?a:b;
12 }
13 int main()
14 {
15 memset(f,127,sizeof(f));
16 scanf("%s",s1+1);
17 scanf("%s",s2+1);
18 f[0][0]=0;
19 scanf("%d%d%d%d%d",&del,&rep,&cop,&ins,&tri);
20 int m=strlen(s1+1),n=strlen(s2+1);
21 for(int i=1;i<=n;i++)
22 f[i][0]=i*ins;
23 for(int i=1;i<=m;i++)
24 f[0][i]=i*del;
25 for(int i=1;i<=n;i++)
26 for(int j=1;j<=m;j++)
27 {
28 f[i][j]=min(f[i][j],f[i][j-1]+del);
29 f[i][j]=min(f[i][j],f[i-1][j-1]+rep);
30 if(s2[i]==s1[j])
31 f[i][j]=min(f[i][j],f[i-1][j-1]+cop);
32 f[i][j]=min(f[i][j],f[i-1][j]+ins);
33 if(i>1&&j>1&&s2[i-1]==s1[j]&&s2[i]==s1[j-1])
34 f[i][j]=min(f[i][j],f[i-2][j-2]+tri);
35 }
36 ans=0x7fffffff;
37 for(int i=1;i<m;i++)
38 ans=min(ans,f[n][i]+(m-i)*del-1);
39 ans=min(ans,f[n][m]);
40 printf("%d",ans);
41 }