hdu 5343 MZL's Circle Zhou(后缀自动机)

题目链接:hdu 5343 MZL's Circle Zhou

题意:

给你两个串A,B,问从A,B中选子串x,y,问x+y可以组成多少个不同的串,x和y可以为空。

题解:

贴一个官方的题解

 

 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 using ll=unsigned long long;
 6 
 7 const int N=1e5+7,tyn=26,M=N*2;
 8 struct SAM{
 9     int tr[M][tyn],f[M],ml[M],ed,last,p,x,r,q;
10     int b[M],d[M]; ll cnt[M];
11     inline int gid(char x){return x-'a';}
12     inline void nc(int s,int &p){
13         ml[p=++ed]=s,f[ed]=cnt[ed]=0,mst(tr[ed],0);
14     }
15     void clear(){ed=0,nc(0,last);}
16     void add(int w){
17         nc(ml[x=last]+1,p),last=p,cnt[p]=1;
18         while(x&&!tr[x][w])tr[x][w]=p,x=f[x];
19         if(!x)f[p]=1;
20         else if(ml[x]+1==ml[q=tr[x][w]])f[p]=q;
21         else{
22             nc(ml[x]+1,r),f[r]=f[q],f[p]=f[q]=r;
23             memcpy(tr[r],tr[q],sizeof(tr[r]));
24             while(x&&tr[x][w]==q)tr[x][w]=r,x=f[x];
25         }
26     }
27     void upright(int mx=0){
28         F(i,0,ed)d[i]=0;
29         F(i,1,ed)d[mx<ml[i]?mx=ml[i]:ml[i]]++;
30         F(i,1,mx)d[i]+=d[i-1];
31         F(i,1,ed)b[d[ml[i]]--]=i;
32     }
33     void build(char *s){for(int i=1;s[i];i++)add(gid(s[i]));}
34 }sam[2];
35 
36 
37 char s[N];
38 int t;
39 
40 void work()
41 {
42     for(int i=sam[1].ed;i;--i)
43     {
44         int x=sam[1].b[i];
45         sam[1].cnt[x]=1;
46         F(j,0,25)
47         {
48             int v=sam[1].tr[x][j];
49             if(v)sam[1].cnt[x]+=sam[1].cnt[v];
50         }
51     }
52 }
53 
54 void solve()
55 {
56     for(int i=sam[0].ed;i;--i)
57     {
58         int x=sam[0].b[i];
59         sam[0].cnt[x]=0;
60         F(j,0,25)
61         {
62             int v=sam[0].tr[x][j];
63             if(v)sam[0].cnt[x]+=sam[0].cnt[v];
64             else sam[0].cnt[x]+=sam[1].cnt[sam[1].tr[1][j]];
65         }
66     }
67     ll ans=sam[0].cnt[1];//x为空的时候已经统计过了
68     F(i,2,sam[0].ed)ans+=sam[0].ml[i]-sam[0].ml[sam[0].f[i]];//y为空的时候
69     printf("%llu\n",ans+1);//+1表示x和y都为空的时候
70 }
71 
72 int main(){
73     scanf("%d",&t);
74     while(t--)
75     {
76         scanf("%s",s+1);
77         sam[0].clear(),sam[0].build(s),sam[0].upright();
78         scanf("%s",s+1);
79         sam[1].clear(),sam[1].build(s),sam[1].upright();
80         work();solve();
81     }
82     return 0;
83 }
View Code

 

posted @ 2017-09-25 20:09  bin_gege  阅读(217)  评论(0编辑  收藏  举报