题目链接 : 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
2 aaaaa cacacSample Output
5 9Hint
For test case 2, the distinct substrings of 'cacac' are as follows: len = 1 : c , a len = 2 : ca , ac len = 3 : cac , aca len = 4 : caca , acac len = 5 : cacac Thus, 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;
}