zoukankan      html  css  js  c++  java
  • HihoCoder1445 后缀自动机二·重复旋律5(后缀自动机 子串种数)

    题意:

    询问串的不同子串个数

    思路:

    后缀自动机每个节点表示以当前字符结尾的一系列后缀,个数为(maxlen - minlen),其中(minlen = maxlen[father])

    代码:

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<bitset>
    #include<string>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include <iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = 1000000 + 10;
    typedef long long ll;
    const ll mod = 998244353;
    typedef unsigned long long ull;
    
    struct SAM{
        struct Node{
            int next[27];
            int fa, maxlen;
            void init(){
                memset(next, 0, sizeof(next));
                fa = maxlen = 0;
            }
        }node[maxn << 1];
        int sz, last;
    
        void init(){
            sz = last = 1;
            node[sz].init();
        }
        void insert(int k){
            int p = last, np = last = ++sz;
            node[np].init();
            node[np].maxlen = node[p].maxlen + 1;
            for(; p && !node[p].next[k]; p = node[p].fa)
                node[p].next[k] = np;
            if(p == 0) {
                node[np].fa = 1;
            }
            else{
                int t = node[p].next[k];
                if(node[t].maxlen == node[p].maxlen + 1){
                    node[np].fa = t;
                }
                else{
                    int nt = ++sz;
                    node[nt] = node[t];
                    node[nt].maxlen = node[p].maxlen + 1;
                    node[np].fa = node[t].fa = nt;
                    for(; p && node[p].next[k] == t; p = node[p].fa)
                        node[p].next[k] = nt;
                }
            }
        }
    
        void solve(){
            ll ans = 0;
            for(int i = 1; i <= sz; i++){
                ans += node[i].maxlen - node[node[i].fa].maxlen;
            }
            printf("%lld
    ", ans);
        }
    }sam;
    char s[maxn];
    int main(){
        sam.init();
        scanf("%s", s);
        int len = strlen(s);
        for(int i = 0; i < len; i++) sam.insert(s[i] - 'a');
        sam.solve();
        return 0;
    }
    
  • 相关阅读:
    在Linux中安装Oracle(较详细图解)
    SecureCRT
    MHA配置文件说明
    MySQL建表规范与常见问题 (go)
    Shell编程时常用的系统文件(转)
    Leetcode: Excel Sheet Column Title
    Leetcode: Find Peak Element
    Leetcode: Intersection of Two Linked Lists
    Leetcode: Majority Element
    Summary: Class Variable vs. Instance Variable && Class Method
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11654893.html
Copyright © 2011-2022 走看看