挺简单的AC自动机,只要求判断该串是否出现即可。只是有点坑,每一串可能出现多次。因此,要存储有哪一串序列序号的信息。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
#define maxn 110000
int n,ch[maxn][52],fail[maxn],tot,root;
int ans[maxn],biao[maxn];
char s[100010],fea[2010];
vector<int>val[maxn];//存储序号信息。
queue<int>q;
int id(char t)
{
if(t>='A'&&t<='Z')return t-'A';
else return t-'a'+26;
}
int newnode()
{
memset(ch[tot],0,sizeof(ch[tot]));
val[tot].clear();
return tot++;
}
void updatea(char *a,int no)
{
int i,len=strlen(a),cur=root;
for(i=0;i<len;i++)
{
if(!ch[cur][id(a[i])])
ch[cur][id(a[i])]=newnode();
cur=ch[cur][id(a[i])];
}
val[cur].push_back(no);
biao[cur]=1;//用1有个好处:进行|运算。
}
void getfail()
{
fail[root]=root;
for(int i=0;i<26;i++)
if(ch[root][i])
{
fail[ch[root][i]]=root;
q.push(ch[root][i]);
}
while(!q.empty())
{
int cur=q.front();
q.pop();
for(int i=0;i<26;i++)
if(!ch[cur][i])
ch[cur][i]=ch[fail[cur]][i];
else
{
fail[ch[cur][i]]=ch[fail[cur]][i];
biao[ch[cur][i]]|=biao[fail[ch[cur][i]]];//需注意
q.push(ch[cur][i]);
}
}
}
void query()
{
int cur=root,i,len=strlen(s);
for(i=0;i<len;i++)
{
cur=ch[cur][id(s[i])];
int temp=cur;
while(temp!=root&&biao[temp])
{
biao[temp]=0;
for(int j=0;j<val[temp].size();j++)
ans[val[temp][j]]=1;
temp=fail[temp];
}
}
}
int main()
{
while(~scanf("%s",s))
{
int i,j,k;
tot=0;
memset(ans,0,sizeof(ans));
root=newnode();
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",&fea);
updatea(fea,i);
}
getchar();
getfail();
query();
for(i=1;i<=n;i++)
if(ans[i])
printf("Y\n");
else printf("N\n");
}
return 0;
}