标签:int eof ring nbsp 因此 接下来 字符 code 相同
3 abcdefg abcdef ab ab mnklj jlknm
1 0 4
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 int maxlen[1002][1002]; 7 int calc(string a, string b){ 8 memset(maxlen,0,sizeof(maxlen)); 9 int alen = a.length(); 10 int blen = b.length(); 11 for(int i = 1; i <= alen; i++){ 12 maxlen[i][0] = i; 13 } 14 for(int i = 1; i <= blen; i++){ 15 maxlen[0][i] = i; 16 } 17 for(int i = 1; i <= alen; i++){ 18 for(int j = 1; j <= blen; j++){ 19 if(a[i-1]==b[j-1]) maxlen[i][j] = maxlen[i-1][j-1]; 20 else maxlen[i][j] = min(min(maxlen[i-1][j],maxlen[i][j-1]),maxlen[i-1][j-1])+1; 21 } 22 } 23 return maxlen[alen][blen]; 24 } 25 int main(){ 26 int n; 27 cin>>n; 28 while(n--){ 29 string a, b; 30 cin>>a>>b; 31 cout<<calc(a, b)<<endl; 32 } 33 return 0; 34 }
备注:这道题乍一看就跟最长公共子序列非常的相像。但我想错了,我本来想的是求出最长公共子序列然后max(alen,blen)-maxlen[alen][blen]就是结果,也过了样例,但这样其实是不对的,只是我举的例子都比较寸。
比如说abcdeeef,gacdeg这两个序列,按照我的错误想法是4步,但关键就在于第一个g,使得他们的距离是5,也就是说需要先删掉g再在a后面加上b,这是两个步骤。也就是说,我最开始想的是,除了公共子序列之外,以长的那个字符串为基准,短的里面不一样的字母要么就删掉,要么就换掉,要么就添加,但这个显然跟短字符串也有关系。比如说如果短字符串是agcdeg,那么直接把第一个g改成b就行,而不需要先删除再添加这两步。
那这道题正确的想法是什么呢?也和公共子序列很相近。array[i][j]表示a字符串的前i个字符构成的子串和b字符串前j个字符构成的子串,的最小操作数。
对比每一个字符a[i-1]和b[j-1],若两个字符相等,即a[i-1] == b[j-1],则不增加距离,因此对应的数组array[i][j]=array[i-1][j-1];若两个字符不相等,则可删除a[i-1]这个字符、删除b[j-1]这个字符,或修改a[i-1]使它与b[i-1]相等。array[i][j]取这三种方法的最小值。选择修改,则array[i][j] = 1 + array[i-1][j-1],若选择删除a[i-1],则array[i][j] = 1 + array[i-1][j],若选择删除b[i-1],则array[i][j] = 1 + array[i][j-1]。
标签:int eof ring nbsp 因此 接下来 字符 code 相同
原文地址:https://www.cnblogs.com/fangziyuan/p/13096757.html