由于要给学弟讲课所以特意去看了一下编辑距离,在poj和hdu上分别做了一题练练。动态规划的一类中编辑距离问题还是比较好理解的。不废话直接上代码。
POJ3356 AGTC
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int dp[2001][2001];
int main()
{
int a,b,i,j,c;
string x,y;
while(cin>>a>>x>>b>>y)
{
memset(dp,0,sizeof(dp));
for(i=0; i<=a; ++i)//初始化
{
dp[i][0]=i;
}
for(i=0; i<=b; ++i)
{
dp[0][i]=i;
}
for(i=0; i<a; ++i)
{
for(j=0; j<b; ++j)
{
c=(x[i]!=y[j]);//直接替换的COST
dp[i+1][j+1]=min(dp[i][j]+c,min(dp[i+1][j]+1,dp[i][j+1]+1));//与添加和删除的COST相比较
}
}
cout<<dp[a][b]<<endl;
}
return 0;
}
HDU4323 Magic Number
这题建议用C++交,可能是我写得太水了,G++一直TLE。。。毕竟复杂度有点高。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
using namespace std;
int dp[1505][1505];
char x[1505][1005],y[1005];
int main()
{
int a,b,i,j,c,t,k,l,p,s,n,m,cas=0,l1,l2[1505];
scanf("%d",&t);
while(t--)
{
cas++;
printf("Case #%d:\n",cas);
scanf("%d%d",&n,&m);
for(i=0; i<n; ++i)
{
scanf("%s",x[i]);
l2[i]=strlen(x[i]);
}
while(m--)
{
s=0;
scanf("%s%d",y,&k);
l1=strlen(y);
for(j=0; j<n; ++j)
{
//memset(dp,0,sizeof(dp));
for(l=0; l<=l2[j]; ++l)
{
dp[l][0]=l;
}
for(l=0; l<=l1; ++l)
{
dp[0][l]=l;
}
for(l=0; l<l2[j]; ++l)
{
for(p=0; p<l1; ++p)
{
c=(x[j][l]!=y[p]);
dp[l+1][p+1]=min(dp[l][p]+c,min(dp[l+1][p]+1,dp[l][p+1]+1));
}
}
if(dp[l2[j]][l1]<=k)
{
s++;
}
}
printf("%d\n",s);
}
}
return 0;
}
HDU4271 Find Black Hand
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#define inf 0x3fffffff
using namespace std;
int dp[11][100005],l1;
char x[100005],y[11][11];
int f(char *a,char *b,int p1,int p2)//dp过程
{
int o=inf,i,j;
for(i=1;i<=p1;++i)
{
dp[i][0]=i;
for(j=1;j<=p2;++j)
{
dp[i][j]=min(dp[i-1][j-1]+(a[i-1]!=b[j-1]),min(dp[i-1][j],dp[i][j-1])+1);
if(i==p1)
{
o=min(o,dp[i][j]);
}
}
}
return o;
}
int main()
{
int i,j,c,t,k,l,p,s,n,Mx,l1,l2;
while(scanf("%s",x)!=EOF)
{
t=-1;
Mx=inf;
l1=strlen(x);
scanf("%d",&n);
for(i=0; i<n; ++i)
{
scanf("%s",y[i]);
l2=strlen(y[i]);
s=inf;
if(l1<10)//由于成环,所以判断是否小于20就行,如果小于20就可以直接dp
{
for(k=0; k<l1; ++k)
{
s=min(s,f(y[i],x+k,l2,l1));
x[l1+k]=x[k];
}
}
else//多于20就在后方加上20个循环字母
{
for(k=0; k<10; ++k)
{
x[l1++]=x[k];
}
s=min(s,f(y[i],x,l2,l1));
}
if(s<Mx||s==Mx&&strcmp(y[i],y[t])<0)
{
Mx=s;
t=i;
}
}
printf("%s %d\n",y[t],Mx);
}
return 0;
}
以上题目均是编辑距离的模板题,用于编辑距离的初学,很有好处。