spoj 694 求一个字符串中不同子串的个数

SPOJ Problem Set (classical)

694. Distinct Substrings

Problem code: DISUBSTR


Given a string, we need to find the total number of its distinct substrings.

Input

T- number of test cases. T<=20;
Each test case consists of one string, whose length is <= 1000

Output

For each test case output one number saying the number of distinct substrings.

Example

Sample Input:
2
CCCCC
ABABA

Sample Output:
5
9

Explanation for the testcase with string ABABA: 
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.


1、用前缀开看不同子串:可以看出--长度为i的字符串一共有i个前缀

2、每一个子串都是某个后缀的前缀,于是问题等价于求所有不同的前缀的个数

然后按sa[1],sa[2]...逐次加入后缀观察:
suffix(sa[i])长度为n-sa[i],一共有n-sa[i]个前缀,减去lcp[i-1](就是与前一个后缀的最长公共前缀的长度),就是新加入的新的前缀的个数

最后求和即可

注意我的lcp[i]指的是suffix(sa[i])和suffix(sa[i+1])的公共前缀的长度

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define MAXN 1011

int n,k;//n=strlen(s);

int Rank[MAXN];
int tmp[MAXN];
char s[MAXN];
int lcp[MAXN],sa[MAXN];

/*使用Rank对sa排序*/
bool cmpSa(int i, int j)
{
    if(Rank[i] != Rank[j])return Rank[i] < Rank[j];
    else
    {   /*下面的Rank[t],已经是以t开头长度小于等于k/2的,
        sa[i]的名次,只是以i开头的后缀,而长度不同*/
        int ri = i+k <=n? Rank[i+k]:-1;
        int rj = j+k <= n ? Rank[j+k]:-1;
        return ri 0)h--;
        for(; j+h



你可能感兴趣的:(数据结构------后缀数组,LCP)