SOJ-4484-后缀数组

来源:互联网 发布:优化的南洋金珠会掉色 编辑:程序博客网 时间:2024/06/12 20:48

题目链接 :  SOJ-4484


The Graver Robbers' Chronicles

Description

One day, Kylin Zhang and Wu Xie are trapped in a graveyard. They find an ancient piece of parchment with a cipher string. After discussion and analysis, they find the password is the total number of the cipher string's distinct substrings. Although Kylin Zhang is powerful and always help his friends get rid of danger, this time he is helpless beacause he is not good at math and programming. As a smart Acmer, can you help them solve this problem so that they can escape from this horrible graveyard.

Input

The first line is an integer T stands for the number of test cases.Then T test case follow.For each test case there is one string.Constraints:T is no bigger than 30.The length of string is no bigger than 50000.Every string only contains lowercase letters.

Output

For each test case, output the answer in a single line. one number saying the number of distinct substrings.

Sample Input

2aaaaacacac

Sample Output

59

Hint

For test case 2, the distinct substrings of 'cacac' are as follows:len = 1 : c , alen = 2 : ca , aclen = 3 : cac , acalen = 4 : caca , acaclen = 5 : cacacThus, total number of distinct substrings is 9.

Author

_L


题目大意:给你一个字符串,求出有多少种不同的子串(连续)包括本身  见样例


题目思路:  看了很久的后缀数组了,,一直都不太懂怎么来的,之后用模板处理一些简单的问题,,这道题关键是对后缀数组height数组的理解,,具体我这里就不描述了,,答案就是所有的子串的个数减去height数组里的值,,这里会超int,,所以要用long long  


AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn = 1e5;int cntA[maxn],sa[maxn],Rank[maxn],cntB[maxn],height[maxn],A[maxn],B[maxn],tsa[maxn];char ch[maxn];int n;void solve(){    for (int i = 0; i < 256; i ++) cntA[i] = 0;    for (int i = 1; i <= n; i ++) cntA[ch[i-1]] ++;    for (int i = 1; i < 256; i ++) cntA[i] += cntA[i - 1];    for (int i = n; i; i --) sa[cntA[ch[i-1]] --] = i;    Rank[sa[1]] = 1;    for (int i = 2; i <= n; i ++)    {        Rank[sa[i]] = Rank[sa[i - 1]];        if (ch[sa[i]-1] != ch[sa[i - 1]-1]) Rank[sa[i]] ++;    }    for (int l = 1; Rank[sa[n]] < n; l <<= 1)    {        for (int i = 0; i <= n; i ++) cntA[i] = 0;        for (int i = 0; i <= n; i ++) cntB[i] = 0;        for (int i = 1; i <= n; i ++)        {            cntA[A[i] = Rank[i]] ++;            cntB[B[i] = (i + l <= n) ? Rank[i + l] : 0] ++;        }        for (int i = 1; i <= n; i ++) cntB[i] += cntB[i - 1];        for (int i = n; i; i --) tsa[cntB[B[i]] --] = i;        for (int i = 1; i <= n; i ++) cntA[i] += cntA[i - 1];        for (int i = n; i; i --) sa[cntA[A[tsa[i]]] --] = tsa[i];        Rank[sa[1]] = 1;        for (int i = 2; i <= n; i ++)        {            Rank[sa[i]] = Rank[sa[i - 1]];            if (A[sa[i]] != A[sa[i - 1]] || B[sa[i]] != B[sa[i - 1]]) Rank[sa[i]] ++;        }    }    for (int i = 1, j = 0; i <= n; i ++)    {        if (j) j --;        while (ch[i + j-1] == ch[sa[Rank[i] - 1] + j-1]) j ++;        height[Rank[i]] = j;    }}int main(){    int t;cin>>t;    while(t--){    scanf("%s",ch);    n=strlen(ch);    solve();    long long ans = (long long)(1+n)*n/2;    for(int i=1;i<=n;i++)        ans-=(long long)height[i];    cout<<ans<<endl;    }    return 0;}


0 0