csu 1305 Substring (后缀数组)
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1305
1305: Substring
Time Limit: 2 Sec Memory Limit: 10 MB Submit: 12 Solved: 2 [Submit][Status][Web Board]Description
Given a string s. The length of s is smaller than 1000. You are to caculate the number of different substrings of s.
Input
There are multiple test cases. Each test case contains one line, with a string s.You may assume that s only contains lowercase letters. You may assume that there are only ten test cases with the length of string s is bigger than 400.
Output
For each test case, you are only to output one integer, the answer.
Sample Input
a ac abcd
Sample Output
1 3 10
【题解】:
后缀数组:用(1+2+。。。+len)-(height数组之后)
【code】:
1 #include <iostream> 2 #include<string.h> 3 #include<stdio.h> 4 5 using namespace std; 6 7 #define maxn 10100 8 #define cls(x) memset(x, 0, sizeof(x)) 9 int wa[maxn],wb[maxn],wv[maxn],wss[maxn]; 10 int cmp(int *r,int a,int b,int l) 11 {return r[a]==r[b]&&r[a+l]==r[b+l];} 12 13 void da(char *r,int *sa,int n,int m) 14 { 15 cls(wa); 16 cls(wb); 17 cls(wv); 18 cls(wss); 19 int i,j,p,*x=wa,*y=wb,*t; 20 for(i=0;i<m;i++) wss[i]=0; 21 for(i=0;i<n;i++) wss[x[i]=r[i]]++; 22 for(i=1;i<m;i++) wss[i]+=wss[i-1]; 23 for(i=n-1;i>=0;i--) sa[--wss[x[i]]]=i; 24 for(j=1,p=1;p<n;j*=2,m=p) 25 { 26 for(p=0,i=n-j;i<n;i++) y[p++]=i; 27 for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; 28 for(i=0;i<n;i++) wv[i]=x[y[i]]; 29 for(i=0;i<m;i++) wss[i]=0; 30 for(i=0;i<n;i++) wss[wv[i]]++; 31 for(i=1;i<m;i++) wss[i]+=wss[i-1]; 32 for(i=n-1;i>=0;i--) sa[--wss[wv[i]]]=y[i]; 33 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) 34 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 35 } 36 return; 37 } 38 int rank[maxn],height[maxn]; 39 void calheight(char *r,int *sa,int n) 40 { 41 cls(rank); 42 cls(height); 43 int i,j,k=0; 44 for(i=1;i<n;i++) rank[sa[i]]=i; 45 for(i=0;i<n;height[rank[i++]]=k) 46 for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k]&&i!=j;k++); 47 return; 48 } 49 50 char ca[maxn * 2]; 51 int sa[maxn]; 52 53 int main() 54 { 55 while (cin >> ca) 56 { 57 int len = strlen(ca); 58 da(ca, sa, len+1, 130); 59 calheight(ca,sa,len+1); 60 int i,sum=0; 61 for(i=1;i<=len;i++) 62 { 63 sum+=height[i]; 64 } 65 cout<<len*(len+1)/2-sum<<endl; 66 cls(ca); 67 } 68 return 0; 69 }