题意:
给定n个单词串,组成一个字典,然后给出m组询问,每组询问为一个单词str,和一个距离edth,询问有字典中有多少个单词满足存在一个前缀使得前缀和单词之间的距离小于等于edth,单词间的距离定义为将询问串,进行插入,删除,替换的最小次数。
思路:
将单词串插入trie树,每个节点的val代表有多少个字符串的前缀为这个节点对应的字符串,
然后进行dp,记录下当前是在trie树上那个节点,匹配了多少个字符,使用了多少次操作,
然后不需要记忆化,因为最多只是整个trie树节点被遍历一遍,然后注意不能够把一个字符串算重复了,
会算重复主要是在一个字符串有两个不同的前缀都满足条件,所以只需要算最短的那个前缀就好了,参考了别人的思路,先把所有的会访问到的节点给标记一下,然后最后再对所有节点进行一遍dfs,最后只要遇到一个标记,下面的前缀就都不用访问了。
代码:
#define debug printf
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<bitset>
#include<vector>
#include<cmath>
using namespace std;
const int maxm=300+10;
const int maxn=300000+100;
int n,m;
int edth;
char str[maxm];
const int SIGMA_SIZE=26;
int idx[256];
void init();
void solve();
int main()
{
init();
while(~scanf("%d",&n)){
solve();
}
return 0;
}
void init()
{
for(int i=0;i<26;i++){
idx['a'+i]=i;
}
}
struct Trie{
static const int MAXNODE=maxn*10;
int ch[MAXNODE][SIGMA_SIZE];
int val[MAXNODE];
int sz;
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
val[0]=0;
}
void insert(char * s)
{
int n=strlen(s);
int u=0;
for(int i=0;i<n;i++){
val[u]++;
int c=idx[s[i]];
if(!ch[u][c]){
val[sz]=0;
memset(ch[sz],0,sizeof(ch[sz]));
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]++;
}
char tmp[maxm];
int ed;
int len;
int ans=0;
unsigned char vis[MAXNODE];
int query(char * s,int e)
{
len=strlen(s);
ed=e;
strcpy(tmp,s);
ans=0;
memset(vis,0,sizeof(vis));
dfs(0,0,0);
getans(0);
return ans;
}
void getans(int u)
{
if(!vis[u]) return;
if(vis[u]==2){
ans+=val[u];
return;
}
for(int c=0;c<SIGMA_SIZE;c++){
if(ch[u][c]){
getans(ch[u][c]);
}
}
}
void dfs(int u,int cur,int e)
{
if(vis[u]==2) return;
vis[u]=1;
// debug("%d %d %d\n",u,cur,e);
if(e>ed) return;
if(cur==len){
if(e<=ed){
vis[u]=2;
}
return;
}
dfs(u,cur+1,e+1);
for(int c=0;c<SIGMA_SIZE;c++){
if(ch[u][c]){
dfs(ch[u][c],cur,e+1);
if(c==idx[tmp[cur]]){
dfs(ch[u][c],cur+1,e);
}
else{
dfs(ch[u][c],cur+1,e+1);
}
}
}
return;
}
};
Trie trie;
void solve()
{
trie.init();
for(int i=0;i<n;i++){
scanf("%s",str);
trie.insert(str);
}
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%s",str);
scanf("%d",&edth);
int ans=trie.query(str,edth);
printf("%d\n",ans);
}
}
/* 4 content common onganize case 7 c 0 con 0 con 2 con 1 com 1 comm 2 cog 1 */