• [模板]后缀自动机


    题面

    给一个字符串 (S) ,求出 (S) 的所有出现次数不为 (1) 的子串的出现次数乘上该子串长度的最大值

    法一:SAM(由于本蒟蒻太菜现在还不会)

    咕咕咕...

    法二:SA

    先后缀排序, 求出 (Height) 数组,然后弄好ST表,从小到大处理每一个前缀,统计完一个前缀的答案后,就删掉它,然后再继续操作左右两个裂开的区间,代码写的很清楚,这里不在赘述。

    SA的做法还是挺巧妙的。

    #include <set>
    #include <cmath>
    #include <cctype>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define fir first
    #define sec second
    #define pb push_back
    #define mp make_pair
    #define LL long long
    #define INF (0x3f3f3f3f)
    #define mem(a, b) memset(a, b, sizeof (a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define Debug(x) cout << #x << " = " << x << endl
    #define tralve(i, x) for (register int i = head[x]; i; i = nxt[i])
    #define For(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
    #define Forr(i, a, b) for (register int (i) = (a); (i) >= (b); -- (i))
    #define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
    #define ____ debug("go
    ")
    
    namespace io {
        static char buf[1<<21], *pos = buf, *end = buf;
        inline char getc()
        { return pos == end && (end = (pos = buf) + fread(buf, 1, 1<<21, stdin), pos == end) ? EOF : *pos ++; }
        inline int rint() {
            register int x = 0, f = 1;register char c;
            while (!isdigit(c = getc())) if (c == '-') f = -1;
            while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getc()));
            return x * f;
        }
        inline LL rLL() {
            register LL x = 0, f = 1; register char c;
            while (!isdigit(c = getc())) if (c == '-') f = -1;
            while (x = (x << 1ll) + (x << 3ll) + (c ^ 48), isdigit(c = getc()));
            return x * f;
        }
        inline void rstr(char *str) {
            while (isspace(*str = getc()));
            while (!isspace(*++str = getc()))
                if (*str == EOF) break;
            *str = '';
        }
        template<typename T> 
            inline bool chkmin(T &x, T y) { return x > y ? (x = y, 1) : 0; }
        template<typename T>
            inline bool chkmax(T &x, T y) { return x < y ? (x = y, 1) : 0; }    
    }
    using namespace io;
    
    const int N = 1e6 + 2;
    
    namespace SA {
        char str[N];
        int n, sa[N], rk[N], ht[N], M;
        void Rsort(int *buc, int *tp) {
            fill(buc, buc + 1 + M, 0);
            For (i, 1, n) buc[rk[i]] ++;
            For (i, 1, M) buc[i] += buc[i - 1];
            Forr (i, n, 1) sa[ buc[ rk[ tp[i] ] ] -- ] = tp[i];
        }
        void SuffixSort() {
            static int buc[N], tp[N];
            M = 76;
            For (i, 1, n) rk[i] = str[i - 1] - '0', tp[i] = i;
            Rsort(buc, tp);
            for (register int len = 1, cnt = 0; cnt < n; len <<= 1, M = cnt) {
                cnt = 0;
                For (i, n - len + 1, n) tp[++cnt] = i;
                For (i, 1, n) if (sa[i] - len > 0) tp[++cnt] = sa[i] - len;
                Rsort(buc, tp); swap(rk, tp); rk[sa[1]] = cnt = 1;
                For (i, 2, n) rk[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + len] == tp[sa[i - 1] + len] ? cnt : ++cnt);
            }
        }
        void getHt() {
            int len = 0;
            For (i, 1, n) {
                if (len) len --;
                int j = sa[rk[i] - 1];
                while (str[j + len - 1] == str[i + len - 1]) len ++;
                ht[rk[i]] = len;
            }
        }
    #define pii pair<int, int>
        int Log[N];
        pii st[N][22];
        void STinit() {
            Log[0] = -1;
            For (i, 1, n) Log[i] = Log[i >> 1] + 1, st[i][0] = mp(ht[i], i);
            for (register int i = 1; n >> i; ++ i) 
                for (register int j = 1; j + (1 << i) - 1 <= n; ++ j) 
                    st[j][i] = min(st[j][i - 1], st[j + (1 << i - 1)][i - 1]);
        }
        pii query(int l, int r) {
            int len = Log[r - l + 1];
            return min(st[l][len], st[r - (1 << len) + 1][len]);
        }
    #undef pii
    }
    
    int ans = 0;
    void solve(int l, int r) {
        if (l > r) return;
        pair<int, int> tmp = SA::query(l, r);
        chkmax(ans, (r - l + 2) * tmp.fir);
        solve(l, tmp.sec - 1);
        solve(tmp.sec + 1, r);
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        file("SA");
    #endif
        scanf("%s", SA::str);
        SA::n = strlen(SA::str);
        SA::SuffixSort();
        SA::getHt();
        SA::STinit();
        solve(1, SA::n);
        cout << ans << endl;
    }
    
  • 相关阅读:
    对List进行子查询及分组
    网格数据库架构设计构想
    推荐一款简单实用的漏洞测试工具:Paros
    用友U9产品SOA设计架构遭技术质疑
    超简单使用MemCached
    不按常规出招
    如何学好AJax、求高手指点
    Begin
    SpringBoot基础
    SpringBoot基础学习(番外9.1)Spring MVC或Spring Boot配置默认访问页面不生效?
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10479040.html
Copyright © 2020-2023  润新知