P3804 后缀自动机模版

Posted acerkoo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3804 后缀自动机模版相关的知识,希望对你有一定的参考价值。

题意

给定一个只包含小写字母的字符串 S,

请你求出 S 的所有出现次数不为 1 的子串的出现次数乘上该子串长度的最大值。

传送门

思路

后缀自动机,parent树上dfs。

code

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e6+10;
const int maxm = maxn<<1;

long long ans = 0;

struct SAM 
    int len[maxm], link[maxm], cnt[maxm];
    int a[maxm], c[maxm];
    int nxt[maxm][26];
    int last, tot;

    int head[maxm], v[maxm], nt[maxm], num;
    void addEdge(int u, int _v) 
        v[num] = _v, nt[num] = head[u];
        head[u] = num++;
    
//    vector<int> g[maxn<<1];

    void init() 
        len[0] = link[0] = 0;
        last = tot = 1;
    

    void extend(int c) 
        c -= 'a';
        int cur = ++tot, p = last;
        len[cur] = len[last] + 1;
        cnt[cur] = 1;
        for (; p && !nxt[p][c]; p = link[p]) nxt[p][c] = cur;
        if(!p) 
            link[cur] = 1;
         else 
            int q = nxt[p][c];
            if(len[q] == len[p]+1) 
                link[cur] = q;
             else 
                int clone = ++tot;
                len[clone] = len[p] + 1;
                memcpy(nxt[clone], nxt[q], sizeof(nxt[q]));
                link[clone] = link[q];
                for (; p!=-1 && nxt[p][c]==q; p=link[p]) nxt[p][c] = clone;
                link[q] = link[cur] = clone;
            
        
        last = cur;
    

    void build() 
        for (int i = 1; i <= tot; ++i) head[i] = -1; num = 0;
        for (int i = 2; i <= tot; ++i)
            addEdge(link[i], i);
    

    void dfs(int x)     // parent树上dfs, vector T了, 前向星2.98s, mx = 494ms
        for (int i = head[x]; ~i; i=nt[i]) 
            dfs(v[i]);
            cnt[x] += cnt[v[i]];
        
        if(cnt[x] > 1) ans = max(ans, 1ll*cnt[x]*len[x]);
    


    void count()  // 利用基数排序模拟dfs过程 , 3.65s, mx = 982ms
        long long ans = 0;
        for (int i = 1; i <= tot; ++i) ++c[len[i]];
        for (int i = 1; i <= tot; ++i) c[i] += c[i-1];
        for (int i = 1; i <= tot; ++i) a[c[len[i]]--] = i;
        for (int i = tot; i; --i) 
            int p = a[i];
            cnt[link[p]] += cnt[p];
            if(cnt[p]>1) ans = max(ans, 1ll*cnt[p]*len[p]);
        
        printf("%lld\n", ans);
    
sam;
char str[maxn];

int main() 
    sam.init();
    scanf("%s", str);
    for (int i = 0; str[i]; ++i) sam.extend(str[i]);
    sam.build();
    sam.dfs(1);
    printf("%lld\n", ans);
//    sam.count();
    return 0;

以上是关于P3804 后缀自动机模版的主要内容,如果未能解决你的问题,请参考以下文章

P3804 模板后缀自动机

洛谷 P3804 模板后缀自动机

P3804 模板后缀自动机

洛谷 P3804 后缀自动机

后缀自动机

109 后缀自动机(SAM)