hdu 6096 String(AC自动机巧妙建图)
题目链接:hdu 6096 String
题意:
给你n个字符串,和q个询问,每个询问给出一个前缀和后缀,问你在这n个字符串中有多少个包含给出的询问,前缀和后缀不能重叠。
题解:
比赛的时候用的hash,无限wa,然后下来后发现他有一组特别的数据专卡我的hash,随便怎么换种子都能卡。真是R了狗了。
然后这题有一个巧妙的办法,用AC自动机去跑。
比如待匹配串是abc,abcd,那么我们将它们转换为abc#abc,abcd#abcd,
然后询问是a c ab cd ,那么就将询问转换为c#a cd#ab。
然后将询问插进AC自动机,将每个带匹配串拿去匹配一下,顺便判断一下长度就行了。
1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=(a);i<=(b);++i) 4 using namespace std; 5 typedef pair<int,int>P; 6 7 const int N=5e5+7; 8 const int AC_N=N,tyn=27; 9 int ans[N],t,n,q,ed,mp[N]; 10 char str[N],pre[N],suf[N]; 11 P s[N]; 12 struct AC_automation{ 13 int tr[AC_N][tyn],Q[AC_N],fail[AC_N],tot; 14 int cnt[AC_N]; 15 inline int getid(char x){return x=='#'?26:x-'a';} 16 void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));} 17 void init(){tot=-1,fail[0]=-1,nw();} 18 int insert(char *s,int len,int x=0){ 19 for(int i=0,w;s[i];x=tr[x][w],i++) 20 if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot; 21 cnt[x]=len; 22 return x; 23 } 24 void build(int head=1,int tail=0){ 25 for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i]; 26 while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++) 27 if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i]; 28 else tr[x][i]=tr[fail[x]][i]; 29 } 30 void ask(char *s,int len){ 31 for(int x=0,i=0,w,j;s[i];i++){ 32 x=tr[x][w=getid(s[i])]; 33 for(j=x;j;j=fail[j])if(cnt[j]&&cnt[j]<=len)ans[j]++; 34 } 35 } 36 }AC; 37 38 39 int main(){ 40 scanf("%d",&t); 41 while(t--) 42 { 43 scanf("%d%d",&n,&q); 44 AC.init();mst(ans,0);ed=0; 45 F(i,1,n) 46 { 47 scanf("%s",str+ed); 48 int len=strlen(str+ed); 49 s[i]=P(ed,len),ed+=len; 50 } 51 F(i,1,q) 52 { 53 scanf("%s%s",pre,suf); 54 strcat(suf,"#"); 55 strcat(suf,pre); 56 mp[i]=AC.insert(suf,strlen(suf)-1); 57 } 58 AC.build(); 59 F(i,1,n) 60 { 61 int st=s[i].first,en=st+s[i].second; 62 F(i,st,en)pre[i-st]=suf[i-st]=str[i]; 63 pre[s[i].second]=suf[s[i].second]=0; 64 strcat(pre,"#"); 65 strcat(pre,suf); 66 AC.ask(pre,s[i].second); 67 } 68 F(i,1,q)printf("%d\n",ans[mp[i]]); 69 } 70 return 0; 71 }