Description
人们在英文字典中查找某个单词的时候可能不知道该单词的完整拼法,而只知道该单词的一个错误的近似拼法,这时人们可能陷入困境,为了查找一个单词而浪费大量的时间。带有模糊查询功能的电子字典能够从一定程度上解决这一问题:用户只要输入一个字符串,电子字典就返回与该单词编辑距离最小的几个单词供用户选择。 字符串a与字符串b的编辑距离是指:允许对a或b串进行下列“编辑”操作,将a变为b或b变为a,最少“编辑”次数即为距离。 删除串中某个位置的字母; 添加一个字母到串中某个位置; 替换串中某一位置的一个字母为另一个字母; JSOI团队正在开发一款电子字典,你需要帮助团队实现一个用于模糊查询功能的计数部件:对于一个待查询字符串,如果它是单词,则返回-1;如果它不是单词,则返回字典中有多少个单词与它的编辑距离为1。
题解:
直接建个trie暴力搞就好了,再用个链表,这样删除、插入、修改都能快速完成。
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=10010;
const int Maxl=25;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,tot=0,Next[Maxl],Last[Maxl],st,ed,T[Maxn*20],ti=0;
char str[Maxl];
struct Trie{int son[27];bool tf;}tr[Maxn*20];
void build_trie()
{
int now=0,len=strlen(str);
for(int i=0;i<len;i++)
{
int x=str[i]-'a'+1;
if(!tr[now].son[x])tr[now].son[x]=++tot;
now=tr[now].son[x];
}tr[now].tf=true;
}
bool work(char *str)
{
int now=0,len=strlen(str);
for(int i=st;i!=ed;i=Next[i])
{
int x=str[i]-'a'+1;
if(!tr[now].son[x])return false;
now=tr[now].son[x];
}
if(tr[now].tf)
{
if(T[now]!=ti){T[now]=ti;return true;}
return false;
}return false;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
{
scanf("%s",str);
build_trie();
}
while(m--)
{
for(int i=0;i<=20;i++)Next[i]=i+1,Last[i]=i-1;st=0;ed=-1;
scanf("%s",str);ti++;
int len=strlen(str),ans=0;
Next[len-1]=-1;
if(work(str)){Next[len-1]=len;puts("-1");continue;}
for(int i=0;i<len;i++)
for(int j=0;j<26;j++)
if(str[i]!=j+'a')
{
char t=str[i];
str[i]=j+'a';
if(work(str))ans++;
str[i]=t;
}//改字符
for(int i=0;i<len;i++)
{
int yl,yn;
if(i==0)st=1;
else if(i==len-1)ed=len-1;
else
{
yl=Last[i];yn=Next[i];
Next[yl]=yn;Last[yn]=yl;
}
if(work(str))ans++;
if(i==0)st=0;
else if(i==len-1)ed=-1;
else Next[yl]=Last[yn]=i;
}//删字符
for(int i=0;i<len;i++)//在这个字符前面加
{
if(i==0)
{
st=len;
Next[st]=0;
for(int j=0;j<26;j++)
{
char c=j+'a';
str[st]=c;
if(work(str))ans++;
}st=0;
}
else
{
for(int j=0;j<26;j++)
{
char c=j+'a';
str[len]=c;
int yl=Last[i];
Next[yl]=len;Next[len]=i;
if(work(str))ans++;
Next[yl]=i;Next[len]=-1;
}
}
}//加字符
Next[len-1]=len;Next[len]=-1;
for(int j=0;j<26;j++)
{
char c=j+'a';
str[len]=c;
if(work(str))ans++;
}
printf("%d\n",ans);
}
}