题目背景:编辑距离
算法设计:DP+分类讨论
例题:51NOD1183
这是一个模板,但模板不是万能的,现在我们来看它的具体算法:
CODE:
#include <iostream>
#include <string>
using namespace std;
string s1,s2;
int dp[1010][1010],len1,len2;
int main()
{
while(cin>>s1>>s2)
{
len1=s1.size();
len2=s2.size();
for(int i=1;i<=len1;++i)
for(int j=1;j<=len2;++j)
dp[i][j]=0;
int flag;
for(int i=0;i<=len1;++i) dp[i][0]=i;
for(int i=0;i<=len2;++i) dp[0][i]=i;
for(int i=1;i<=len1;++i)
for(int j=1;j<=len2;++j)
{
if(s1[i-1]==s2[j-1])
flag=0;
else
flag=1;
int tmp=min(dp[i-1][j]+1,dp[i][j-1]+1);
dp[i][j]=min(dp[i-1][j-1]+flag,tmp);
//dp[i][j]=max(dp[i-1][j-1]+flag,dp[i-1][j]+1,dp[i-1][j-1]+1);/**/
}
/*for(int i=1;i<=len1;++i)
{
for(int j=1;j<=len2;++j)
cout<<dp[i][j]<<" ";
cout<<endl;
}*/
cout<<dp[len1][len2]<<endl;
}
}
/*
kitten
sitting
*/
关于状态转移方程:
现在来解释这个状态转移方程:
1.我们已经知道串s1,串s2之间修改有三种操作:
一、修改:这对应于:
二、删除:对应与:
三:加入:把s2加入到s1的前面:
2.因为我们是要求最小的编辑距离,所以转移的时候,要比较这三种操作的最小值,
3.修改是什么意思:我们要看s1的第 i 个字符要不要修改成s2的第 j 个字符,如果这两个字符是相同的,那么就要改0个字符,否则,就要改 1 个字符,所以,这个 flag 就是 要修改的字符的个数的意思
4.什么是删除?这里我们要把s1的第i个字符给删除,那么这个时候的编辑距离就是dp[i-1,j]+1距离
5.同理,我们把s2的第 j 个字符加入到 s1 的 第 i 个字符前面,那么这份时候的编辑距离就是dp[i,j-1]的距离le
6.之后,只要比较这三种操作哪一种花费最小即可。
初始化数组的问题: