UVALive 6869(后缀数组)

 

传送门: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

 

你可能感兴趣的:(后缀数组)