题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4323
题目大意,求一个字典中,与询问串的最小编辑距离小于等于d的个数。
题目思路:dp很容易想,比赛的时候由于以为会超时,一直不敢写,结果直接暴力就可以过。。题解上说可用BK-tree优化,结果优化结果很不理想,和暴力差不多。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
using namespace std;
#define inf 0xfffffff
#define N 155
#define M 50005
char a[2000][15],b[2000][15];
int d;
int dp[20][20],cnt;
int ans;
struct node
{
char *str;
int next[12];
int cnt;
void init()
{
cnt=0;
memset(next,0,sizeof(next));
}
}tri[3200];
int cal(char *a,char *b)
{
int len1=strlen(a);
int len2=strlen(b);
int g,l;
dp[0][0]=0;
for(g=1;g<=len1;g++)
dp[g][0]=g;
for(l=1;l<=len2;l++)
dp[0][l]=l;
for(g=1;g<=len1;g++)
for(l=1;l<=len2;l++)
{
if(a[g-1]==b[l-1])
dp[g][l]=min(dp[g-1][l-1],min(dp[g-1][l]+1,dp[g][l-1]+1));
else
dp[g][l]=min(dp[g-1][l-1]+1,min(dp[g-1][l]+1,dp[g][l-1]+1));
}
return dp[len1][len2];
}
void insert(char *s)
{
int p,x;
p=0;
while(1)
{
x=cal(s,tri[p].str);
// printf("%d\n",x);
if(x==0)
{
tri[p].cnt++;
break;
}
if(!tri[p].next[x])
{
tri[++cnt].init();
tri[p].next[x]=cnt;
tri[cnt].cnt++;
tri[cnt].str=s;
break;
}
p=tri[p].next[x];
}
}
void query(char *s,int p,int d)
{
int i,x;
x=cal(s,tri[p].str);
// printf("x %d\n",x);
if(x<=d)
{ans+=tri[p].cnt;
// printf("%d\n",tri[p].cnt);
}
i=(d-x>0)?d-x:1;
for(;i<=d+x&&i<=10;i++)
{
if(tri[p].next[i])
query(s,tri[p].next[i],d);
}
}
int main()
{
int t,i,n,m;
int count=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
cnt=0;
tri[0].init();
tri[0].str=a[0];
tri[0].cnt=1;
for(i=0;i<n;i++)
{
scanf("%s",a[i]);
if(i>0)
insert(a[i]);
// printf("%s\n",a[i]);
}
printf("Case #%d:\n",count++);
for(i=0;i<m;i++)
{
scanf("%s%d",b[i],&d);
ans=0;
query(b[i],0,d);
printf("%d\n",ans);
}
}
return 0;
}