码迷,mamicode.com
首页 > 其他好文 > 详细

P3804 后缀自动机模版

时间:2019-10-03 13:08:45      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:struct   class   count()   memcpy   ret   last   name   传送门   vector   

题意

给定一个只包含小写字母的字符串 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 后缀自动机模版

标签:struct   class   count()   memcpy   ret   last   name   传送门   vector   

原文地址:https://www.cnblogs.com/acerkoo/p/11619372.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!