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
",ans[mp[i]]);
69     }
70     return 0;
71 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/7345663.html