【模板】字尾自動機SAM
阿新 • • 發佈:2018-12-17
參考題目:洛谷P3804
解析:
其實這個東西的理解的話,說難沒有那麼難,說簡單也不是很簡單。
這裡先貼一個程式碼,什麼時候再更新吧。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
typedef struct SAM_node *point;
struct SAM_node{
int len, cnt;
point fa,son[26];
SAM_node():len(0),fa(NULL){memset(son,0,sizeof son);}
inline point clear(int l=0){
fa=NULL;
len=l;
memset(son,0,sizeof son);
return this;
}
};
cs int N=1000006;
struct SAM{
SAM_node nd[N<<1];
point now,last,pos[N<<1];
int bin[N<<1];
SAM():now(nd),last(nd){}
inline void clear(){
for(;now>nd;--now)now->clear();
last=now=nd->clear();
}
inline void push_back(char c){
c-='a';
point cur=++now;
cur->len=last->len+1;
cur->cnt= 1;
point p=last;
for(;p&&!p->son[c];p=p->fa)p->son[c]=cur;
if(!p)cur->fa=nd;
else if(p->son[c]->len==p->len+1)cur->fa=p->son[c];
else {
point clone=++now,q=p->son[c];
*clone=*q;
clone->len=p->len+1;
clone->cnt=0;
q->fa=cur->fa=clone;
for(;p&&p->son[c]==q;p=p->fa)p->son[c]=clone;
}
last=cur;
}
inline ll calc(){
re ll ans=0;
for(point re i=nd;i<=now;++i)++bin[i->len];
for(int re i=1;i<=now-nd;++i)bin[i]+=bin[i-1];
for(point re i=nd;i<=now;++i)pos[bin[i->len]--]=i;
for(int re i=now-nd;i;--i){
if(pos[i]->fa)pos[i]->fa->cnt+=pos[i]->cnt;
if(pos[i]->cnt^1)ans=max(ans,(ll)pos[i]->cnt*pos[i]->len);
}
return ans;
}
}sam;
char s[N];int len;
signed main(){
scanf("%s",s+1);len=strlen(s+1);
for(int re i=1;i<=len;++i)sam.push_back(s[i]);
printf("%lld",sam.calc());
return 0;
}