题意:求重复但不重叠的子串数。
解题思路:height分组。枚举长度L,将height数组进行分组,使得每一组的height都大于L,若有一组的最大的sa值和最小的sa值之差大于L,则说明该组内存在一个符合条件的子串。
1 /* 2 *Author: Zhaofa Fang 3 *Created time: 2013-05-06-19.28 4 *Language: C++ 5 */ 6 #include <cstdio> 7 #include <cstdlib> 8 #include <sstream> 9 #include <iostream> 10 #include <cmath> 11 #include <cstring> 12 #include <algorithm> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 #include <queue> 17 #include <map> 18 #include <set> 19 using namespace std; 20 21 typedef long long ll; 22 #define DEBUG(x) cout<< #x << ':' << x << endl 23 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 24 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 25 #define REP(i,n) for(int i=0;i<n;i++) 26 #define REPD(i,n) for(int i=n-1;i>=0;i--) 27 #define PII pair<int,int> 28 #define PB push_back 29 #define MP make_pair 30 #define ft first 31 #define sd second 32 #define lowbit(x) (x&(-x)) 33 #define INF (1<<30) 34 35 36 const int maxn = 1011; 37 char s[maxn]; 38 int sa[maxn],t1[maxn],t2[maxn],c[maxn]; 39 int rank[maxn],height[maxn]; 40 41 void getHeight(int n){ 42 int k = 0; 43 for(int i=1;i<=n;i++)rank[sa[i]] = i; 44 for(int i=0;i<n;i++){ 45 if(k)k--; 46 int j = sa[rank[i]-1]; 47 while(s[i+k] == s[j+k])k++; 48 height[rank[i]] = k; 49 } 50 } 51 bool cmp(int *r,int a,int b,int l){ 52 return (r[a] == r[b] && r[a+l]==r[b+l]); 53 } 54 void build_sa(int m,int n){ 55 int i,*x=t1,*y=t2,k,p; 56 for( i=0;i<m;i++)c[i] = 0; 57 for( i=0;i<n;i++)c[x[i]=s[i]] ++; 58 for( i=1;i<m;i++)c[i] += c[i-1]; 59 for( i=n-1;i>=0;i--)sa[-- c[x[i]]] = i; 60 for(k=1,p=0;p<n;m=p,k<<=1){ 61 p=0; 62 for(i=n-k;i<n;i++)y[p++] = i; 63 for(i=0;i<n;i++)if(sa[i]>=k)y[p++] = sa[i]-k; 64 for(i=0;i<m;i++)c[i] = 0; 65 for(i=0;i<n;i++)c[x[y[i]]] ++; 66 for(i=1;i<m;i++)c[i] += c[i-1]; 67 for(i=n-1;i>=0;i--)sa[-- c[x[y[i]]]] = y[i]; 68 swap(x,y); 69 p = 1; x[sa[0]] = 0; 70 for(i=1;i<n;i++) 71 x[sa[i]] = cmp(y,sa[i-1],sa[i],k)?p-1:p++; 72 } 73 getHeight(n-1); 74 } 75 int solve(int n){ 76 int ans = 0; 77 for(int i=1;i<=n/2;i++){ 78 int mi = sa[1],mx = sa[1]; 79 for(int j=2;j<=n+1;j++){ 80 if(j!=n+1 && height[j]>=i){ 81 mi = min(mi,sa[j]); 82 mx = max(mx,sa[j]); 83 }else { 84 if(mx - mi >= i)ans++; 85 mx = mi = sa[j]; 86 } 87 } 88 } 89 return ans; 90 } 91 int main(){ 92 //freopen("in","r",stdin); 93 //freopen("out","w",stdout); 94 while(gets(s)){ 95 if(s[0] == '#')break; 96 int n = strlen(s); 97 REP(i,n)s[i] = s[i] - 'a' + 1; 98 build_sa(28,n+1); 99 printf("%d\n",solve(n)); 100 } 101 return 0; 102 }