SPOJ1812
来自蒟蒻XXJ的做题记录
题解可以去看看wjmzbmr的ppt
在这里记录几个问题:
1.居然在extend的过程中忘记了==要更新lth
2.居然直接用了儿子匹配到的长度去更新父亲==
3.按照lth进行排序就可以出来一个天然的按照先儿子后父亲的顺序排好的序列。
代码:
#include<bits/stdc++.h>
#define mem(i,j) memset(i,j,sizeof(i))
#define mcy(i,j) memcpy(i,j,sizeof(i))
using namespace std;
const int MAXN=200010;
const int INF=1008610086;
int n;
void hello(){
freopen("a.in","r",stdin);
freopen("a.ans","w",stdout);
}
struct SAM{
int trans[MAXN][26],lth[MAXN],fa[MAXN];
int last,cnt;
int mp[MAXN],mx[MAXN];
SAM(){
cnt=0;last=++cnt;
mem(trans,0);mem(fa,0);
for(int i=1;i<MAXN;i++) mp[i]=INF;
}
void extend(int c){
int np=++cnt,p=last;last=cnt;
lth[np]=lth[p]+1;
for(;p&&!trans[p][c];p=fa[p]) trans[p][c]=np;
if(!p) fa[np]=1;
else{
int q=trans[p][c];
if(lth[q]==lth[p]+1) fa[np]=q;
else{
int nq=++cnt;lth[nq]=lth[p]+1;
mcy(trans[nq],trans[q]);
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
for(;p&&trans[p][c]==q;p=fa[p]) trans[p][c]=nq;
}
}
}
void build(char str[]){
int len=strlen(str);
for(int i=0;i<len;i++) extend(str[i]-'a');
}
}sam;
char c[MAXN];
int rank[MAXN];
bool cmp(int i,int j){
return sam.lth[i]>sam.lth[j];
}
void input(){
scanf("%s",c);
sam.build(c);
for(int i=1;i<=sam.cnt;i++) rank[i]=i;
sort(rank+1,rank+sam.cnt+1,cmp);
}
void xxj(){
while(scanf("%s",c)==1){
int len=strlen(c),ans(0),p=1;
for(int i=0;i<len;i++){
int x=c[i]-'a';
if(sam.trans[p][x]){
++ans;
p=sam.trans[p][x];
if(sam.mx[p]<ans) sam.mx[p]=ans;
}
else{
while(p&&!sam.trans[p][x]) p=sam.fa[p];
if(!p) p=1,ans=0;
else{
ans=sam.lth[p]+1;
p=sam.trans[p][x];
if(sam.mx[p]<ans) sam.mx[p]=ans;
}
}
}
for(int i=1;i<=sam.cnt;i++){
int index=rank[i];
if(sam.mp[index]>sam.mx[index]) sam.mp[index]=sam.mx[index];
if(!sam.fa[index]) continue;
if(sam.mx[index]) sam.mx[sam.fa[index]]=sam.lth[sam.fa[index]];
}
mem(sam.mx,0);
}
}
void output(){
int ans(0);
for(int i=1;i<=sam.cnt;++i){
if(sam.mp[i]==INF) continue;
ans=max(ans,sam.mp[i]);
}
cout<<ans<<endl;
}
int main(){
// hello();
input();
xxj();
output();
return 0;
}