zoukankan      html  css  js  c++  java
  • 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 && 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
    ", 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
    ", ans);
    //    sam.count();
        return 0;
    }
    
  • 相关阅读:
    iOS开发代码规范
    数组去重方法总结
    iOS进阶学习-网络之数据安全
    OC 动态类型,动态绑定,动态加载
    ios运行某些工程时屏幕上下出现黑边的解决办法
    流程控制和数组(关于JAVA基础注意事项)
    高级函数
    源码
    sql s2 学期的学习
    Java 学习笔记
  • 原文地址:https://www.cnblogs.com/acerkoo/p/11619372.html
Copyright © 2011-2022 走看看