码迷,mamicode.com
首页 > 其他好文 > 详细

【后缀自动机】51nod 淋漓尽致子串

时间:2015-09-27 21:23:17      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:

通道

题意:最大周期串有多少个,子串不算。

思路:建好SAM后,fail和next跳,删除前缀相同和后缀相同即可

代码:

技术分享
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <string>
#include <algorithm>

using namespace std;

const int MAX_N = 200007;

typedef unsigned long long ll;

struct SAM {
    int val[MAX_N], fa[MAX_N], c[26][MAX_N];
    int tot, last;
    int which[MAX_N]; //该节点的字符 
    inline int newNode(int step) {
        val[++tot] = step;
        fa[tot] = 0;
        for (int i = 0; i < 26; ++i) c[i][tot] = 0;
        return tot;
    }
    inline void extend(int k) {
        int p = last;
        int np = newNode(val[last] + 1);
        which[np] = k;
        while (p && !c[k][p]) c[k][p] = np, p = fa[p];
        if (!p) fa[np] = 1;
        else {
            int q = c[k][p];
            if (val[q] == val[p] + 1) fa[np] = q;
            else {
                int nq = newNode(val[p] + 1);
                which[nq] = k;
                for (int i = 0; i < 26; ++i) c[i][nq] = c[i][q];
                fa[nq] = fa[q]; 
                fa[q] = fa[np] = nq;
                while (p && c[k][p] == q) c[k][p] = nq, p = fa[p];
            }
        }
        last = np;
    }
    inline int add(int k) {
        extend(k);
    }
    inline void init() {
        tot = 0;
        last = newNode(0);
    }
} suf;

char A[MAX_N>>1], B[MAX_N>>1];
int id[MAX_N], cnt[MAX_N], C[MAX_N];

int main() {
    scanf("%s", B);
    suf.init(); 
    for (int i = 0; B[i]; ++i) suf.add(B[i] - a);
    int len = strlen(B);
    for (int i = 1; i <= suf.tot; ++i) ++C[suf.val[i]];
    for (int i = 1; i <= len; ++i) C[i] += C[i - 1];
    for (int i = 1; i <= suf.tot; ++i) id[C[suf.val[i]]--] = i;
    int j = 1;
    for (int i = 0; i < len; ++i) {
        ++cnt[suf.c[B[i] - a][j]];
        j = suf.c[B[i] - a][j];
    }
    for (int i = suf.tot; i > 0; --i) {
        int d = id[i];
        cnt[suf.fa[d]] += cnt[d];
    }
    for (int i = 1; i <= suf.tot; ++i) {
        int d = id[i];
        for (int j = 0; j < 26; ++j) {
            if (suf.c[j][d] == 0) continue;
            if (cnt[suf.c[j][d]] > 1) {
                cnt[d] = 1;
                break;
            } 
        }
        while (d && cnt[suf.fa[d]] > 1) d = suf.fa[d], cnt[suf.fa[d]] = 1;
    }
    int ans = 0;
    for (int i = suf.tot; i > 1; --i) {
        if (cnt[i] > 1) 
            ++ans;
    }
    printf("%d\n", ans);
    return 0;
}
View Code

 

【后缀自动机】51nod 淋漓尽致子串

标签:

原文地址:http://www.cnblogs.com/Rojo/p/4842644.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!