首页 > 其他 > 详细

4516: [Sdoi2016]生成魔咒

时间:2019-02-12 22:32:05      阅读:167      评论:0      收藏:0      [点我收藏+]

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 aaa(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\n", Ans);
}
int main() {
    int n = read(); 
    for (int i = 1; i <= n; ++i) {
        int x = read();
        extend(x);
    }
    return 0;
}

 

4516: [Sdoi2016]生成魔咒

原文:https://www.cnblogs.com/mjtcn/p/10367238.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!