Luogu P3804 【模板】后缀自动机

注意空间开两倍

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template<class T>inline void read(T &num) {
    register char ch; register int flg = 1;
    while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
    for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar());
    num *= flg;
}
const int MAXN = 1000005;
const int C = 26;
struct SAM {
    int sz, last, len[MAXN<<1], link[MAXN<<1], ch[MAXN<<1][C], size[MAXN<<1];
    inline void init() {
        sz = last = 0;
        len[0] = size[0] = 0;
        link[0] = -1;
        ++sz;
        //memset(ch, 0, sizeof ch);
    }
    inline void insert(int c) {
        int cur = sz++, p;
        len[cur] = len[last] + 1;
        size[cur] = 1;
        for(p = last; ~p && !ch[p][c]; p = link[p]) ch[p][c] = cur;
        if(p == -1) link[cur] = 0;
        else {
            int q = ch[p][c];
            if(len[p] + 1 == len[q]) link[cur] = q;
            else {
                int clone = sz++;
                len[clone] = len[p] + 1;
                link[clone] = link[q];
                memcpy(ch[clone], ch[q], sizeof ch[q]);
                for(; ~p && ch[p][c] == q; p = link[p]) ch[p][c] = clone;
                link[cur] = link[q] = clone;
            }
        }
        last = cur;
    }
}sam;
int n, seq[MAXN<<1], cnt[MAXN];
int main() {
    char ch; sam.init();
    while((ch=getchar())!='\n') ++n, sam.insert(ch-'a');
    for(int i = 0; i < sam.sz; ++i) ++cnt[sam.len[i]];
    for(int i = 1; i <= n; ++i) cnt[i] += cnt[i-1];
    for(int i = sam.sz-1; ~i; --i) seq[cnt[sam.len[i]]--] = i;
    LL ans = 0;
    for(int i = sam.sz; i > 1; --i) {
        sam.size[sam.link[seq[i]]] += sam.size[seq[i]];
        if(sam.size[seq[i]] > 1) //题目要求出现次数大于1
            ans = max(ans, 1ll * sam.len[seq[i]] * sam.size[seq[i]]);
    }
    printf("%lld\n", ans);
}

posted @ 2019-12-14 14:51  _Ark  阅读(121)  评论(0)    收藏  举报