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 }

 

你可能感兴趣的:(height)