hdu 3518 Boring counting(后缀数组+height分组)

题意:求重复但不重叠的子串数。

解题思路:height分组。枚举长度L,将height数组进行分组,使得每一组的height都大于L,若有一组的最大的sa值和最小的sa值之差大于L,则说明该组内存在一个符合条件的子串。

View Code
  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 }

 

posted @ 2013-05-06 20:22  發_  阅读(167)  评论(0编辑  收藏  举报