#include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; int sa[N],rk[N],hei[N],x[N],y[N],c[N]; char s[N]; void Rsort(R n,R m){ for(R i=1;i<=n;++i)++c[x[i]]; for(R i=2;i<=m;++i)c[i]+=c[i-1]; for(R i=n;i;--i)sa[c[x[y[i]]]--]=y[i]; } int main(){ R n=fread(s+1,1,N,stdin)-1,m=122; for(R i=1;i<=n;++i)x[i]=s[i],y[i]=i; Rsort(n,m); for(R k=1,p=0;k<=n;k<<=1,p=0){ for(R i=n-k+1;i<=n;++i)y[++p]=i; for(R i=1;i<=n;++i)if(sa[i]>k)y[++p]=sa[i]-k; memset(c+1,0,4*m);Rsort(n,m);memcpy(y+1,x+1,4*n); x[sa[1]]=p=1; for(R i=2;i<=n;++i) x[sa[i]]=p+=y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]; if((m=p)==n)break; } for(R i=1;i<=n;++i)rk[sa[i]]=i; for(R i=1,p=0;i<=n;++i){ for(p-=(bool)p;s[i+p]==s[sa[rk[i]-1]+p];++p); hei[rk[i]]=p; } for(R i=1;i<=n;++i)printf("%d ",sa[i]);puts(""); for(R i=1;i<=n;++i)printf("%d ",rk[i]);puts(""); for(R i=1;i<=n;++i)printf("%d ",hei[i]);puts(""); return 0; }
#include<bits/stdc++.h> #define RG register #define R RG int using namespace std; const int N=2e6+9; int lst=1,nod=1,ch[N][26],fa[N],len[N]; char s[N]; void Extend(R c){ R f=lst,p=lst=++nod; len[p]=len[f]+1; while(f&&!ch[f][c])ch[f][c]=p,f=fa[f]; if(!f){fa[p]=1;return;} R x=ch[f][c]; if(len[x]==len[f]+1){fa[p]=x;return;} R y=++nod;memcpy(ch[y],ch[x],104); len[y]=len[f]+1;fa[y]=fa[x];fa[x]=fa[p]=y; while(f&&ch[f][c]==x)ch[f][c]=y,f=fa[f]; } int main(){ for(char c=getchar();c>='a';c=getchar())Extend(c-'a'); long long ans=0; for(R i=1;i<=nod;++i)ans+=len[i]-len[fa[i]]; cout<<ans<<endl; return 0; }
注意兩個特判
第一個特判是由於已經有這個狀態了
第二個特判是由於分裂出y後,p失去意義了
大多數時候,模式串是獨立的,能夠每次把lst重賦值爲1
若是模式串是Trie的話,DFS建SAM會被卡成\(O(葉節點個數×|S|)\)
正確寫法是在BFS遍歷Trie時進行Extend,詳情參考XZY巨佬的總結
洛谷P3346 [ZJOI2015]諸神眷顧的幻想鄉html
#include<bits/stdc++.h> #define LL long long #define RG register #define R RG int #define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin)) using namespace std; const int SZ=1<<19,N=2e5+9,M=10*N; char buf[SZ],*ie=buf+SZ,*ip=ie-1; inline int in(){ G;while(*ip<'-')G; R x=*ip&15;G; while(*ip>'-'){x*=10;x+=*ip&15;G;} return x; } int he[N],ne[N],to[N]; char s[N]; namespace GSAM{ int nod=1,ch[2*M][10],fa[2*M],len[2*M]; int Extend(R f,R c){ if(len[ch[f][c]]==len[f]+1)return ch[f][c]; R p=++nod; len[p]=len[f]+1; while(f&&!ch[f][c])ch[f][c]=p,f=fa[f]; if(!f)return fa[p]=1,p; R x=ch[f][c]; if(len[x]==len[f]+1)return fa[p]=x,p; R y=++nod,lst=len[p]==len[f]+1?y:p; memcpy(ch[y],ch[x],sizeof(ch[y])); len[y]=len[f]+1;fa[y]=fa[x];fa[x]=fa[p]=y; while(f&&ch[f][c]==x)ch[f][c]=y,f=fa[f]; return lst; } LL calc(){ LL ans=0; for(R i=1;i<=nod;++i)ans+=len[i]-len[fa[i]]; return ans; } } namespace Trie{ int p,ch[M][10],lst[M],q[M]; void dfs(R&u,R x,R f){ if(!u)u=++p; for(R i=he[x];i;i=ne[i]) if(to[i]!=f)dfs(ch[u][s[to[i]]],to[i],x); } void bfs(){ lst[0]=1; for(R h=0,t=0;h<=t;++h) for(R x=q[h],y,i=0;i<10;++i) if((y=ch[x][i]))lst[q[++t]=y]=GSAM::Extend(lst[x],i); } } int main(){ R n=in(),m=in(); for(R i=1;i<=n;++i)s[i]=in(); for(R i=1,p=0;i<n;++i){ R x=in(),y=in(); ne[++p]=he[x];to[he[x]=p]=y; ne[++p]=he[y];to[he[y]=p]=x; } for(R i=1;i<=n;++i) if(!ne[he[i]])Trie::dfs(Trie::ch[0][s[i]],i,0); Trie::bfs(); printf("%lld\n",GSAM::calc()); return 0; }
不會c++
會板子了qaq
洛穀日報——強勢圖解迴文自動機
洛谷P3649 [APIO2014]迴文串數組
#include<bits/stdc++.h> #define LL long long #define R register int using namespace std; const int N=3e5+9; char s[N]; int lst,nod=1,f[N],ch[N][26],len[N],sum[N]; inline void Extend(R i,R c){ R p=lst; while(s[i-len[p]-1]!=s[i])p=f[p]; if(!ch[p][c]){ R q=f[p]; while(s[i-len[q]-1]!=s[i])q=f[q]; f[++nod]=ch[q][c];//注意先求fail再給ch賦值 len[ch[p][c]=nod]=len[p]+2; } ++sum[lst=ch[p][c]]; } int main(){ len[f[0]=f[1]=1]=-1; cin>>(s+1); R n=strlen(s+1);LL ans=0; for(R i=1;i<=n;++i)Extend(i,s[i]-'a'); for(R x=nod;x;--x){//PAM建出來自帶拓撲序直接for ans=max(ans,(LL)sum[x]*len[x]); sum[f[x]]+=sum[x]; } cout<<ans<<endl; return 0; }
【Done】重複旋律1(一個串的最長k重可重疊子串)
【Todo】重複旋律2(一個串的最長多重不可重疊子串)
【Done】重複旋律3(兩個串的最長公共子串)
【Done】重複旋律4(一個串的週期重複次數最多的子串)
【Done】SAM基本概念
【Done】重複旋律5(一個串的本質不一樣子串個數)
【Done】重複旋律6(一個串的最長k重可重疊子串(對全部的k求答案))
【Todo】重複旋律7(一個數字串的本質不一樣子串的數值和)
【Todo】重複旋律8(一個文本串中與某模式串循環同構的子串計數)
【Todo】重複旋律9(字符串上的博弈)ui
【Done】洛谷CF666E Forensic Examination
【Todo】洛谷CF700E Cool Slogans
【Todo】HDU5343 MZL's Circle Zhou(vjudge)
【Todo】HDU4622 Reincarnation(vjudge)(可作\(n,q\le10^5\))spa
【Todo】BZOJ3682 Phorni
【Todo】BZOJ2555 SubString.net
http://www.javashuo.com/article/p-uluothxc-g.html
http://www.javashuo.com/article/p-rybgasap-s.html
https://blog.csdn.net/qq_39898877/article/details/82729385
http://www.javashuo.com/article/p-zanbgplm-dd.htmlcode