码迷,mamicode.com
首页 > 编程语言 > 详细

UVALive 6869(后缀数组)

时间:2015-04-27 12:58:48      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

 

传送门:Repeated Substrings

题意:给定一个字符串,求至少重复一次的不同子串个数。

分析:模拟写出子符串后缀并排好序可以发现,每次出现新的重复子串个数都是由现在的height值减去前一个height值。

技术分享
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 100010;
typedef long long LL;
int sa[maxn];
int t1[maxn], t2[maxn], c[maxn];
int ran[maxn], height[maxn];
int s[maxn];
char str[maxn];

void build_sa(int s[], int n, int m) {
    int i, j, p, *x = t1, *y = t2;
    for (i = 0; i < m; i++) c[i] = 0;
    for (i = 0; i < n; i++) c[x[i] = s[i]]++;
    for (i = 1; i < m; i++) c[i] += c[i-1];
    for (i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;

    for (j = 1; j <= n; j <<= 1) {
        p = 0;
        for (i = n-j; i < n; i++) y[p++] = i;
        for (i = 0; i < n; i++)
            if (sa[i] >= j)
                y[p++] = sa[i] - j;
        for (i = 0; i < m; i++) c[i] = 0;
        for (i = 0; i < n; i++) c[x[y[i]]]++;
        for (i = 1; i < m; i++) c[i] += c[i-1];
        for (i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];

        swap(x, y);
        p = 1, x[sa[0]] = 0;
        for (i = 1; i < n; i++)
            x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p-1 : p++;

        if (p >= n) break;
        m = p;
    }
}

void getHeight(int s[],int n) {
    int i, j, k = 0;
    for (i = 0; i <= n; i++)
        ran[sa[i]] = i;
    for (i = 0; i < n; i++) {
        if (k) k--;
        j = sa[ran[i]-1];
        while (s[i+k] == s[j+k]) k++;
        height[ran[i]]=k;
    }
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%s", str);
        int n = strlen(str);
        for (int i = 0; i <= n; i++)
            s[i] = str[i];
        build_sa(s, n+1, 128);
        getHeight(s, n);
        LL ans = 0;
        for (int i = 1; i <= n; i++)
        {
            if(height[i]>height[i-1])ans+=height[i]-height[i-1];
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

 

UVALive 6869(后缀数组)

标签:

原文地址:http://www.cnblogs.com/lienus/p/4459801.html

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