题目:定义一套操作方法将两个不相同的字符串变得相同,具体操作如下:
修改一个字符(“a”——>“b”) 增加一个字符(“abdd”——>“aebdd”) 删除一个字符(“travelling”——>“traveling”)字符串的距离s:使两个字符串相等的操作
相似度:1/(s+1)。
思路:
字符串a:长度m
字符串b:长度n
计算使得a[1..m]和b[1..n]相同需要变换的次数:
当a[1] == b[1]:计算a[2..m]和b[2..n]
当a[1] != b[1]
1.删除a中第一个字符:计算a[2..m]和b[1..n]
2.删除b中第一个字符:计算a[1..m]和b[2..n]
3.修改a中第一个字符:计算a[2..m]和b[2..n]
4.修改b中第一个字符:计算a[2..m]和b[2..n]
5.增加a串中的第一个字符到b串前:计算a[2..m]和b[1..n]
6.增加b串中的第一个字符到a串前:计算a[1..m]和b[2..n]
一次操作后,计算:
a[2..m]和b[1..n]
a[1..m]和b[2..n]
a[2..m]和b[2..n]
使用递归可以容易解答:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int min(int x, int y){
if(x > y){
return y;
}else{
return x;
}
}
int caculate(char a[], int startA, int endA, char b[], int startB, int endB){
int t1=0, t2=0, t3=0, tmp=0;
//注意出口条件
if(startA > endA){
if(startB > endB){
return 0;
}else{
return endB - startB + 1;
}
}
if(startB > endB){
if(startA > endA){
return 0;
}else{
return endA - startA + 1;
}
}
if(a[startA] == b[startB]){
return caculate(a,startA+1,endA,b,startB+1,endB);
}else{
t3 = caculate(a,startA,endA,b,startB+1,endB);
t1 = caculate(a,startA+1,endA,b,startB,endB);
t2 = caculate(a,startA+1,endA,b,startB+1,endB);
tmp = min(t1,t2);
return min(tmp,t3) + 1;
}
}
int main(){
char a[100],b[100];
int lenA, lenB ,ret;
scanf("%s%s",a,b);
lenA = strlen(a);
lenB = strlen(b);
ret = caculate(a,0,lenA-1,b,0,lenB-1);
printf("%d",ret);
system("pause");
return main();
}
使用备忘录对上述递归进行改进:
flag[i][j]表示a[i][lenA-1]和b[j][lenB-1]的变换次数:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int flag[100][100];
int min(int x, int y){
if(x > y){
return y;
}else{
return x;
}
}
int caculate(char a[], int startA, int endA, char b[], int startB, int endB){
int t1=0, t2=0, t3=0, tmp=0;
//出口条件
if(startA > endA){
if(startB > endB){
return 0;
}else{
flag[startA][startB] = endB - startB + 1;
return endB - startB + 1;
}
}
if(startB > endB){
if(startA > endA){
return 0;
}else{
flag[startA][startB] = endA - startA + 1;
return endA - startA + 1;
}
}
if(a[startA] == b[startB]){
if(flag[startA+1][startB+1] > 0){
return flag[startA+1][startB+1];
}else{
flag[startA][startB] = caculate(a,startA+1,endA,b,startB+1,endB);
return flag[startA][startB];
}
}else{
if(flag[startA][startB+1] > 0){
t1 = flag[startA][startB+1];
}else{
t1 = caculate(a,startA,endA,b,startB+1,endB);
}
if(flag[startA+1][startB] > 0){
t2 = flag[startA+1][startB];
}else{
t2 = caculate(a,startA+1,endA,b,startB,endB);
}
if(flag[startA+1][startB+1] > 0){
t3 = flag[startA+1][startB+1];
}else{
t3 = caculate(a,startA+1,endA,b,startB+1,endB);
}
tmp = min(t1,t2);
flag[startA][startB] = min(tmp,t3) + 1;
return flag[startA][startB];
}
}
int main(){
char a[100],b[100];
int lenA, lenB ,ret,i,j;
scanf("%s%s",a,b);
for(i=0; i<100; i++)
for(j=0; j<100; j++)
flag[i][j] = 0;
lenA = strlen(a);
lenB = strlen(b);
ret = caculate(a,0,lenA-1,b,0,lenB-1);
printf("%d",ret);
system("pause");
return main();
}