[bzoj4516] [Sdoi2016]生成魔咒

  强行上hash。。复杂度两个log。。

  把字符串倒过来。就是每次加一个后缀。。就变成问一个后缀会产生多少个不同子串的板子题了。

  听说是SAM板子题..这辈子学不会SAM系列>_<

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 #define ull unsigned long long
 7 using namespace std;
 8 const int maxn=100233,base=1e9+9;
 9 int lc[maxn],rc[maxn],val[maxn],rnd[maxn],tot;
10 ull pre[maxn],jc[maxn];
11 int s[maxn],sa[maxn],rk[maxn];
12 int i,j,k,n,m,AFT,PRE,V,rt;
13 ll ans;
14  
15  
16 int ra;char rx;
17 inline int read(){
18     rx=getchar(),ra=0;
19     while(rx<'0'||rx>'9')rx=getchar();
20     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
21 }
22 inline int getlcp(int a,int b){
23     if(s[a]!=s[b])return 0;
24     if(a>b)swap(a,b);
25     int r=n-b+1;
26     a--,b--;
27     if(pre[n]-pre[b]*jc[r]==pre[a+r]-pre[a]*jc[r])return r;
28     int l=1,mid;
29     while(l<r)
30         if(pre[b+(mid=l+r+1>>1)]-pre[b]*jc[mid]==pre[a+mid]-pre[a]*jc[mid])
31             l=mid;else r=mid-1;
32     return l;
33 }
34 inline bool cmp(int a,int b){
35     int lcp=getlcp(a,b);
36     return s[a+lcp]<s[b+lcp];
37 }
38 inline void getsa(){
39     int i;
40     for(i=jc[0]=1;i<=n;i++)pre[i]=pre[i-1]*base+s[i],jc[i]=jc[i-1]*base,sa[i]=i;
41     sort(sa+1,sa+1+n,cmp);
42     for(i=1;i<=n;i++)rk[sa[i]]=i;//,printf("   %d",sa[i]);puts("");
43 //  for(i=1;i<=n;i++)printf("   %d",rk[i]);puts("");
44 }
45  
46 inline void lturn(int &x){int R=rc[x];rc[x]=lc[R],lc[R]=x,x=R;}
47 inline void rturn(int &x){int L=lc[x];lc[x]=rc[L],rc[L]=x,x=L;}
48 inline void insert(int &x){
49     if(!x){x=++tot,val[x]=V,rnd[x]=rand()+tot;return;}
50     if(V<val[x]){
51         insert(lc[x]);
52         if(rnd[lc[x]]<rnd[x])rturn(x);
53     }else{
54         insert(rc[x]);
55         if(rnd[rc[x]]<rnd[x])lturn(x);
56     }
57 }
58 void getpre(int x){
59     if(!x)return;
60     if(val[x]<V)PRE=val[x],getpre(rc[x]);
61     else getpre(lc[x]);
62 }
63 void getaft(int x){
64     if(!x)return;
65     if(val[x]>V)AFT=val[x],getaft(lc[x]);
66     else getaft(rc[x]);
67 }
68 int main(){
69     n=read();
70     for(i=n;i;i--)s[i]=read();
71 //      n=1e5;  for(i=n;i;i--)s[i]=1;
72     getsa();//return 233;
73     ans=1,V=rk[n],insert(rt);printf("%lld
",ans);
74     for(i=n-1;i;i--){
75         PRE=AFT=0,V=rk[i],getpre(rt),getaft(rt);
76 //      printf("i:%d  rk:%d   pre:%d  aft:%d
",i,rk[i],PRE,AFT);
77         if(!PRE||!AFT)ans+=n-i+1-getlcp(i,sa[PRE|AFT]);
78         else ans+=n-i+1-max(getlcp(i,sa[PRE]),getlcp(i,sa[AFT]));
79         printf("%lld
",ans);
80         V=rk[i],insert(rt);
81     }//printf("  %lld
",ans);
82     return 0;
83 }
84 
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5598186.html