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;
    }
    
  • 相关阅读:
    JDK各版本新特性总结
    Java MyBatis3(3)分页插件PageHelper
    Kubernetes--K8S
    MySQL 查看表结构
    查看mysql库大小,表大小,索引大小
    Linux服务器安装Oracle服务端总结
    怎样玩转千万级别的数据
    Markdown 新手指南
    深入理解Java:注解(Annotation)基本概念
    深入理解Java:注解(Annotation)自定义注解入门
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11654893.html
Copyright © 2011-2022 走看看