【BZOJ3756】Pty的字符串(广义后缀自动机)

题意:

 

 思路:论文题

 

 建立Trie树的后缀自动机需要换这个长的板子

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 typedef pair<ll,int>P;
 11 #define N  800010
 12 #define M  8100000
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pi acos(-1)
 17 #define mem(a,b) memset(a,b,sizeof(a))
 18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 20 #define lowbit(x) x&(-x)
 21 #define Rand (rand()*(1<<16)+rand())
 22 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 23 #define ls p<<1
 24 #define rs p<<1|1
 25 
 26 const int MOD=1e9+7,inv2=(MOD+1)/2;
 27       double eps=1e-6;
 28       int INF=1e9;
 29       ll inf=5e13;
 30       int dx[4]={-1,1,0,0};
 31       int dy[4]={0,0,-1,1};
 32 
 33 char s[M];
 34 int p,np,q,nq,k,cas,n;
 35 int pos[N];
 36 
 37 int read()
 38 {
 39    int v=0,f=1;
 40    char c=getchar();
 41    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 42    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 43    return v*f;
 44 }
 45 
 46 struct sam
 47 {
 48     int cnt;
 49     int fa[N<<1],ch[N<<1][26];
 50     int st[N<<1],b[N<<1],bl[N<<1],to[N<<1],size[N<<1];
 51     ll f[N<<1];
 52     sam()
 53     {
 54         cnt=1;
 55     }
 56 
 57     int add(int p,int x)
 58     {
 59         if(ch[p][x])
 60         {
 61             q=ch[p][x];
 62             if(st[q]==st[p]+1)
 63             {
 64                 size[q]++;
 65                 return q;
 66             }
 67              else
 68              {
 69                  st[nq=++cnt]=st[p]+1; size[nq]=1;
 70                  memcpy(ch[nq],ch[q],sizeof ch[q]);
 71                 //t[nq]=t[q];
 72                  fa[nq]=fa[q];
 73                  fa[q]=nq;
 74                  while(ch[p][x]==q)
 75                  {
 76                      ch[p][x]=nq;
 77                      p=fa[p];
 78                  }
 79                  return nq;
 80              }
 81         }
 82          else
 83          {
 84                 st[np=++cnt]=st[p]+1; size[np]=1;
 85                 while(p&&!ch[p][x])
 86                 {
 87                     ch[p][x]=np;
 88                     p=fa[p];
 89                 }
 90                 if(!p) fa[np]=1;
 91                  else
 92                  {
 93                         int q=ch[p][x];
 94                         if(st[q]==st[p]+1) fa[np]=q;
 95                          else
 96                          {
 97                                 nq=++cnt; st[nq]=st[p]+1;
 98                                 memcpy(ch[nq],ch[q],sizeof ch[q]);
 99                                 fa[nq]=fa[q];
100                                 fa[q]=fa[np]=nq;
101                                 while(ch[p][x]==q)
102                                 {
103                                     ch[p][x]=nq;
104                                     p=fa[p];
105                                 }
106                          }
107                  }
108            }
109         return np;
110     }
111 
112     void solve()
113     {
114         //printf("cnt=%d\n",cnt);
115         rep(i,1,cnt) b[st[i]]++;
116         rep(i,1,cnt) b[i]+=b[i-1];
117         rep(i,1,cnt) bl[b[st[i]]--]=i;
118         scanf("%s",s+1);
119         int n=strlen(s+1);
120         per(i,cnt,1) size[fa[bl[i]]]+=size[bl[i]];
121         //rep(i,1,cnt) printf("%d\n",size[i]);
122         size[1]=0;
123         rep(i,1,cnt)
124         {
125             int p=bl[i];
126             f[p]=f[fa[p]]+1ll*(st[p]-st[fa[p]])*size[p];
127         }
128         ll ans=0;
129         p=1;
130         int L=0;
131         rep(i,1,n)
132         {
133             int x=s[i]-'a';
134             if(ch[p][x]) L++,p=ch[p][x];
135              else
136              {
137                  while(p&&!ch[p][x]) p=fa[p];
138                  if(p) L=st[p]+1,p=ch[p][x];
139                   else L=0,p=1;
140              }
141              if(p!=1) ans+=f[fa[p]]+1ll*(L-st[fa[p]])*size[p];
142         }
143         printf("%lld\n",ans);
144     }
145 
146 }sam;
147 
148 int main()
149 {
150     freopen("1.in","r",stdin);
151     freopen("1.out","w",stdout);
152     n=read();
153     pos[1]=1;
154     rep(i,2,n)
155     {
156         int x=read();
157         scanf("%s",s+1);
158         pos[i]=sam.add(pos[x],s[1]-'a');
159     }
160     sam.solve();
161     return 0;
162 }

 

posted on 2019-09-12 16:12  myx12345  阅读(179)  评论(0编辑  收藏  举报

导航