zoukankan      html  css  js  c++  java
  • 4516: [Sdoi2016]生成魔咒

    4516: [Sdoi2016]生成魔咒

    链接

    题意:

      求本质不同的子串。

    分析:

      后缀数组或者SAM都可以。

      考虑SAM中每个点的可以表示的子串是一个区间min(S)~max(S),把每个点的这个区间加起来即可。

      字符集有点大,可以用map。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 200005;
    map<int,int> ch[N];
    int fa[N], len[N], Index = 1, Last = 1;
    LL Ans;
    
    void extend(int c) {
        int np = ++Index, p = Last; 
        len[np] = len[p] + 1;
        for (; p && ch[p].find(c) == ch[p].end(); p = fa[p]) ch[p][c] = np;
        if (!p) fa[np] = 1;
        else {
            int Q = ch[p][c];
            if (len[Q] == len[p] + 1) fa[np] = Q;
            else {
                int NQ = ++Index;
                fa[NQ] = fa[Q];
                ch[NQ] = ch[Q];
                len[NQ] = len[p] + 1;
                fa[Q] = fa[np] = NQ;
                for (; p && ch[p].find(c) != ch[p].end() && ch[p][c] == Q; p = fa[p]) ch[p][c] = NQ;
            }
        }
        Last = np;
        Ans += len[np] - len[fa[np]]; // max(np)=len[np], min(np)=len[fa[p]] + 1
        printf("%lld
    ", Ans);
    }
    int main() {
        int n = read(); 
        for (int i = 1; i <= n; ++i) {
            int x = read();
            extend(x);
        }
        return 0;
    }
  • 相关阅读:
    Java实现水仙花数
    CSS3属性选择器
    Word快捷键
    Java实现百钱买百鸡
    某专业人士给中国计算机专业学生的建议
    经典名言警句
    面试问题和思路
    情商
    Java注意的地方
    唯大英雄能真本色——Leo鉴书34
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10367238.html
Copyright © 2011-2022 走看看