首页 > 代码库 > CSU-1632 Repeated Substrings[后缀数组求重复出现的子串数目]

CSU-1632 Repeated Substrings[后缀数组求重复出现的子串数目]

 

评测地址:https://cn.vjudge.net/problem/CSU-1632

Description

求字符串中所有出现至少2次的子串个数

Input

第一行为一整数T(T<=10)表示用例组数,每组用例占一行为一个长度不超过100000的字符串

Output

对于每组用例,输出该串中所有出现至少两次的子串个数

Sample Input

3

aabaab

aaaaa

AaAaA

Sample Output

5

4

5

Solution

Ans=summax(height(i)-height(i-1),0)

 

#include<cstdio>#include<cstring>using namespace std;const int N=1e5+5;int T,n,ans,c[N],sa[N],tsa[N],trank[N],rank[N],h[N];char s[N];void DA(int maxx=256){    memset(c,0,sizeof c);int p;    for(int i=1;i<=n;i++) c[rank[i]=s[i]]++;    for(int i=2;i<=maxx;i++) c[i]+=c[i-1];    for(int i=n;i;i--) sa[c[rank[i]]--]=i;    trank[sa[1]]=p=1;    for(int i=2;i<=n;i++){        if(rank[sa[i]]!=rank[sa[i-1]]) p++;        trank[sa[i]]=p;    }    for(int i=1;i<=n;i++) rank[i]=trank[i];    for(int k=1;p<n;k<<=1,maxx=p){        p=0;        for(int i=n-k+1;i<=n;i++) tsa[++p]=i;        for(int i=1;i<=n;i++) if(sa[i]>k) tsa[++p]=sa[i]-k;        memset(c,0,sizeof c);        for(int i=1;i<=n;i++) trank[i]=rank[tsa[i]];        for(int i=1;i<=n;i++) c[trank[i]]++;        for(int i=2;i<=maxx;i++) c[i]+=c[i-1];        for(int i=n;i;i--) sa[c[trank[i]]--]=tsa[i];        trank[sa[1]]=p=1;        for(int i=2;i<=n;i++){            if(rank[sa[i]]!=rank[sa[i-1]]||rank[sa[i]+k]!=rank[sa[i-1]+k]) p++;            trank[sa[i]]=p;        }        for(int i=1;i<=n;i++) rank[i]=trank[i];    }    for(int i=1,k=0;i<=n;i++){        int j=sa[rank[i]-1];        while(s[i+k]==s[j+k]) k++;        h[rank[i]]=k;if(k>0)k--;    }}void GO(){    ans=0;    for(int i=1;i<=n;i++) if(h[i]>h[i-1]) ans+=h[i]-h[i-1];    printf("%d\n",ans);}int main(){    scanf("%d",&T);    while(T--){        scanf("%s",s+1);n=strlen(s+1);        DA();        GO();    }    return 0;}

 

 

 

CSU-1632 Repeated Substrings[后缀数组求重复出现的子串数目]