题意:给定n个串和m次询问,对于每次询问,给定一个字符串t,和最大操作次数a,
问在n个字符串中有多少个能在规定的次数之内变成字符串t.
说明:字符串的基本操作仅为:删除、插入和修改一个字符这三种操作
我们把进行了一次上述三种操作的任意一种操作称为进行了一步字符基本操作。
两个字符串的编辑距离:两个字符串a和b,通过上述的基本操作,把a变成b或b变成a,
需要的最少基本字符操作步数称为字符串a和字符串b的编辑距离
分析:分别求出n个字符串与字符串t之间的编辑距离,并判断是否不大于最大操作步数
关键点:求编辑距离
设dp[i+1][j+1]:
为第一个字符串长度为i的子串到第二个字符串的长度为j的子串的编辑距离
动态规划公式:
i = 0 且 j = 0,dp[i][j] = 0
i = 0 且 j > 0,dp[i][j] = j
i > 0 且j = 0,dp[i][j] = i
i ≥ 1 且 j ≥ 1 ,dp[i+1][j+1] == min{ dp[i][j+1]+ 1, dp[i+1][j] + 1, dp[i][j] + f(i, j) },
当第一个字符串的第i个字符不等于第二个字符串的第j个字符时,
f(i, j) = 1;否则,f(i, j) = 0
#include<stdio.h> #include<string.h> int dp[15][15],len1,len2; char s[1530][15],t[15]; int min(int a,int b,int c) { if(b<a) a=b; if(c<a) a=c; return a; } void my_dp(int pos) //计算字符串s[pos]和t的编辑距离 { int i,j,dp1,dp2,dp3; len1=strlen(s[pos]); len2=strlen(t); for(i=0;i<=len1;i++) dp[i][0]=i; for(j=0;j<=len2;j++) dp[0][j]=j; for(i=0;i<len1;i++) for(j=0;j<len2;j++){ dp1=dp[i][j+1]+1; dp2=dp[i+1][j]+1; dp3=dp[i][j]; if(s[pos][i]!=t[j]) dp3++; dp[i+1][j+1]=min(dp1,dp2,dp3); } } int main() { int m,n,T,i,k,a,ans; scanf("%d",&T); for(k=1;k<=T;k++){ printf("Case #%d:\n",k); scanf("%d%d",&m,&n); for(i=1;i<=m;i++) scanf("%s",s[i]); while(n--){ scanf("%s%d",t,&a); ans=0; for(i=1;i<=m;i++){ my_dp(i); if(dp[len1][len2]<=a) ans++; } printf("%d\n",ans); } } return 0; }
hdu 4323 Magic Number (dp,编辑距离)
原文:http://blog.csdn.net/acm_code/article/details/41082201