T4 字符串的修改 题解
Posted lichangjian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了T4 字符串的修改 题解相关的知识,希望对你有一定的参考价值。
有 A=a1a2a3„am,B=b1b2b3„bn 两个字符串(均为小写字母)现在要通过以下操作将 A
或 A 的一个后缀修改为 B:
1. 删除 删除掉 A 中的某一个字符。
2. 添加 将某一个字符添加到 A 中任意位置。
3. 替换 将 A 中某一字符替换为另一个。
求出最小操作次数
第一行为字符串 A。第二行为字符串 B(长度均不超过 1000)。
题目描述很有让人爆搜的想法啊,看到数据,嗯,绝望了。
以这种大小明显不是爆搜可以解决的吧,看起来很像dp的样子呢,试试吧(重点我也没想到别的算法)
本来我是在写后缀的,dp[i][j]=a的后i个数要多少步才能变成b的前j个数。
但是这个代码有点太恶心人了,我脑子有点乱,感觉这不是什么好主意……
我就改了一下主意:dp[i][j]=a的前i个数要多少步才能变成b的前j个数。
大家想想啊,虽然这个是前缀,但如果前缀没什么用是不是可以忽略掉,竟然这样的话,代码清晰,思路也清晰就不是事了。
emm,写完了,但出了一点小问题。
大家都知道字符串第一个字符的下表是0,竟然是0的话,那么就不能出现什么dp[x-1]之类的东西,会崩掉的。
这不是很大的事情,但我处理的有些繁琐,导致自己出的一个数据一直过不去,还不知道为啥。
然后就来了一波操作,让输入的字符串下标整体向后移动了一下。
减少了奇怪的操作,问题解决了。
虽然我不知道为什么会有问题,但我知道是哪里出了问题,替代掉它就可以了。
一些奇怪的问题解决了,接下来是正经的dp了。
通过前面的说法,dp[i][j]表示a的前i个字符改变成b的前j个字符的次数。
我们可以得到一个简单好想的状态转化方程,就像新手礼包一样。dp[i][j]=min(dp[i-1][j-1]+bj,min(dp[i-1][j]+1,dp[i][j-1]));
emm,有点长,同学们可能看不懂,简单解释一下,我们把他分开,变成3部分
第一部分:dp[i-1][j-1]+bj
bj的意思是新加进来的两个字符是否相等,相等就抵消了嘛,不想等还要处理……
相等的话bj就是0,不相等就是1咯。
第二部分:dp[i-1][j]+1
这个部分对应的是删除一个字符,很好理解的,删一个就会变成dp[i-1][j],反过来想想就得到了。
第三部分:dp[i][j-1]+1
这个也很好写,对应的是增加一个字符,和上一个同理。
讲了这么长,该放个代码了
#include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<cstring> using namespace std; long long dp[1005][1005],ac,bc,bj; char a[1005],b[1005]; int main() { freopen("str.in","r",stdin); freopen("str.out","w",stdout); cin>>a+1>>b+1; ac=strlen(a+1); bc=strlen(b+1); for(int i=1;i<=ac;i++) { dp[i][0]=0; } for(int i=1;i<=bc;i++) { dp[0][i]=i; } for(int i=1;i<=ac;i++) { for(int j=1;j<=bc;j++) { if(a[i]==b[j]) { bj=0; }else { bj=1; } dp[i][j]=min(dp[i-1][j-1]+bj,min(dp[i][j-1]+1,dp[i-1][j]+1)); } } cout<<dp[ac][bc]<<endl; return 0; }
思路写了这么多,代码只有40行(如果我不是这个码风可能还短),dp这种东西想起来有点难,写起来还是挺好写的。
附加:想不明白可以私下问我。看不看的见就随缘吧。
以上是关于T4 字符串的修改 题解的主要内容,如果未能解决你的问题,请参考以下文章