过完年了,又回来集训。
年后第一题。
这道题写了一个晚上,可能太久没有写过了,有点生疏了。
最后还是请ztz大神来帮忙看了看。
总结:
1.AC自动机的数组是根据所输入模板的总字符来定。
2.对于tot=1,以及初始化的时候将它的儿子全指向自己都是必须的。
3.对于getans时不了解,就手动模拟。
纪念一下!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define Set(aa,bb) memset(aa,bb,sizeof(aa))
using namespace std;
const int maxn=100010;
struct Aho_corasick_automaton{
int trie[maxn][130],fail[maxn],q[maxn],w[maxn],ans[maxn],_,tot,n,m;
bool vis[maxn];
char all[maxn];
void init(){
tot=1;
For(i,0,128)trie[0][i]=1;
Set(fail,0);
}
int newnode(){
fail[++tot]=0;
vis[tot]=0;
For(i,0,127) trie[tot][i]=0;
return tot;
}
void insert(char *s,int id){
int len=strlen(s),p=1;
For(i,0,len-1){
int j=s[i];
p=trie[p][j]?trie[p][j]:trie[p][j]=newnode();
}
w[p]=id;
vis[p]=1;
}
void got(int now){
For(i,0,127){
int ls=trie[fail[now]][i];
if(trie[now][i]) fail[trie[now][i]]=ls,vis[trie[now][i]]|=vis[ls];
else trie[now][i]=ls;
}
}
void getfail(){
int f=0,l=1;
q[1]=1;
while(f<l){
int top=q[++f];
For(i,0,127){
if(trie[top][i]) q[++l]=trie[top][i];
}
got(top);
}
}
void getans(char *s){
int len=strlen(s),p=1;
For(i,0,len-1){
int j=s[i];
if(j>=33 && j<=126)
{
if(!trie[p][j])p=1;
p=trie[p][j];
if(!p)p=1;
}
else
{
p=1;
continue;
}
for(int l=p;l>1;l=fail[l]){
if(!vis[l])break;
if(w[l]) ans[++_]=w[l];
}
}
}
void work(){
init();
scanf("%d%d",&n,&m);
For(i,1,n){
scanf("%s",all);
insert(all,i);
}
getfail();
scanf("%d",&m);
int sum=0;
For(i,1,m){
scanf("%s",all);
_=0;
getans(all);
if(!_) continue;
sort(ans+1,ans+_+1);
++sum;
printf("web %d: ",i);
For(j,1,_-1) printf("%d ",ans[j]);
printf("%d",ans[_]);
puts("");
}
printf("total: %d",sum);
puts("");
}
}d;
int main(){
d.work();
return 0;
}