首先建一个数组记忆化储存两个字符串之间的编辑距离,我命名为ed[ ][ ]
其次就是初始化这个用于记忆化的数组ed,因为既然是动态规划,逐本溯源,一定会由边界条件;
(这里我命名第一个字符串为source,设其字符串长度为n;第二个字符串名字为target,设其字符串长度为m)
由于这是一个意义为两个字符串间距离比较的数组(这个数组记录了source这个串长度由0到n形成的每个子串与target这个串长度由0到m之间形成的每个子串之间的编辑距离):那么,边界条件必然为
source长度为0时,source与target之间的编辑距离就是此时target的子串的长度,
以及, target长度为0时,source与target之间的编辑距离就是此时source的子串的长度.
到现在为止,初始化已经完事了
接下来进行递归:
ed[i][j]会有两种情况:
1.source[i]==target[j] 此时ed[i][j]=ed[i-1][j-1]
2.source[i] != target[j]
-------此时的ed[i][j]可能是由三种情况递推而来的:
1)由ed[i-1][j-1]通过将source[i](或是:将target[j])变换为target[j](变换为source[i])得来的
故,此种递推方程为ed[i][j]=ed[i-1][j-1]+1
2)由ed[i-1][j]通过将source[i]删去(由于source[i] != target[j],所以把不一样的那个字符( 即 source[i] )删去)得来的
故,此种递推方程为ed[i][j]=ed[i-1][j]+1
3)由ed[i][j-1]通过将target[j]删去(由于source[i] != target[j],所以把不一样的那个字符( 即 target[j] )删去)得来的
故,此种递推方程为ed[i][j]=ed[i][j-1]+1
现在我们递推关系也捋清楚了,接下来上代码吧
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<string>
using namespace std;
#define maxx 20
int ed[maxx+5][maxx+5];
int ED(string source,string target)
{
int n=source.length();
int m=target.length();
if(m==0) return n;
if(n==0) return m;
memset(ed,0,sizeof(ed));
for(int i=0;i<=n;i++)
{
ed[i][0]=i;
}
for(int i=0;i<=m;i++)
{
ed[0][i]=i;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int cost;
if(source[i-1]==target[j-1])
cost=0;
else
cost=1;
ed[i][j]=min( ed[i-1][j-1]+cost,min( ed[i-1][j]+1 , ed[i][j-1]+1 ) );
}
}
return ed[n][m];
}
int main()
{
string s,t;//s:source t:target
while(cin>>s>>t)
{
cout<<ED(s,t)<<endl;
}
return 0;
}
说实在的,可能是大佬们都觉得这个比较简单,网上很多都是一笔带过,哎,,,,
那我就写的细致点吧,也当是自己再捋顺一遍思路了