109 后缀自动机(SAM)


视频链接:

 

P3804 【模板】后缀自动机 (SAM)。

// Luogu P3804 【模板】后缀自动机 (SAM)
#include 
#include 
#include 
using namespace std;

typedef long long LL;
const int N=2e6+10;
int h[N], e[N], ne[N], idx;
char str[N];
LL cnt[N], ans;
int tot=1, cur=1;
int len[N], fa[N], ch[N][26];

void extend(int c){
  // p指针,cur当前点,q链接点,nq新链接点
  int p = cur; cur = ++tot;
  len[cur]=len[p]+1; cnt[cur]=1;
  for(; p&&!ch[p][c]; p=fa[p]) ch[p][c]=cur;

  if(p==0) fa[cur]=1;//1.c是新字符
  else{
    int q=ch[p][c];
    if(len[q]==len[p]+1)fa[cur]=q;//2.有链接点
    else{ //3.无链接点
      int nq = ++tot; //新建链接点
      len[nq]=len[p]+1; 
      fa[nq]=fa[q]; fa[q]=nq; fa[cur]=nq;
      memcpy(ch[nq],ch[q],sizeof(ch[q]));
      for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq; 
    }
  }
}
void add(int a, int b){
    e[++idx]=b, ne[idx]=h[a], h[a]=idx;
}
void dfs(int u){
    for(int i=h[u]; i; i=ne[i]){
        dfs(e[i]);
        cnt[u] += cnt[e[i]];
    }
    if(cnt[u]>1) ans=max(ans, cnt[u]*len[u]);
}
int main(){
    scanf("%s", str);
    for(int i=0;str[i];i++) extend(str[i]-'a');
    for(int i=2; i<=tot; i++) add(fa[i], i);
    dfs(1);
    printf("%lld\n", ans);
    return 0;
}

相关