【hdu3518】Boring counting

题意:找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠)。

后缀数组

枚举字串长度h,对于每一次的h,利用height数组,找出连续的height大于等于h的里面最左端和最右端得为之l和r。
如果l+h-1<r的话,说明没有重叠,答案加1.

 

 1 #include<algorithm>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 using namespace std;
 7 
 8 #define N 1010
 9 
10 int wa[N],wb[N],ws[N],wv[N];
11 int sa[N],rank1[N],height[N];
12 int r[N];
13 
14 char s[N];
15 
16 int n,ans;
17 
18 int cmp(int *r,int a,int b,int l)
19 {
20     return r[a]==r[b] && r[a+l]==r[b+l];
21 }
22 
23 void da(int *r,int n,int m)
24 {
25     int i,j,p,*x=wa,*y=wb,*t;
26     for (i=0;i<m;i++) ws[i]=0;
27     for (i=0;i<n;i++) ws[x[i]=r[i]]++;
28     for (i=1;i<m;i++) ws[i]+=ws[i-1];
29     for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
30     for (j=1,p=1;p<n;j<<=1,m=p)
31     {
32         for (p=0,i=n-j;i<n;i++) y[p++]=i;
33         for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
34         for (i=0;i<n;i++) wv[i]=x[y[i]];
35         for (i=0;i<m;i++) ws[i]=0;
36         for (i=0;i<n;i++) ws[wv[i]]++;
37         for (i=1;i<m;i++) ws[i]+=ws[i-1];
38         for (i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
39         for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
40             x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p-1 : p++;
41     }
42     return ;
43 }
44 
45 void calheight(int *r,int n)
46 {
47     int i,j,k=0;
48     for (i=1;i<=n;i++) rank1[sa[i]]=i;
49     for (i=0;i<n;height[rank1[i++]]=k)
50         for (k ? k-- : 0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
51     return ;
52 }
53 
54 int main()
55 {
56     while (scanf("%s",s)!=EOF && s[0]!='#')
57     {
58         ans=0;
59         n=strlen(s);
60         for (int i=0;i<n;i++)
61             r[i]=s[i]-'a'+2;
62         r[n]=0;
63         da(r,n+1,30);
64         calheight(r,n);
65         for (int i=1;i<=n/2;i++)
66         {
67             int l=n+1,r=0;
68             for (int j=2;j<=n;j++)
69             {
70                 if (height[j]>=i)
71                 {
72                     r=max(r,sa[j-1]);
73                     r=max(r,sa[j]);
74                     l=min(l,sa[j-1]);
75                     l=min(l,sa[j]);
76                 }
77                 else
78                 {
79                     if (r-l>=i)
80                         ans++;
81                     r=0;
82                     l=n+1;
83                 }
84             }
85             if (r-l>=i)
86                 ans++;
87         }
88         printf("%d\n",ans);
89     }
90     return 0;
91 }

 

posted @ 2016-04-09 17:48  Yangjiyuan  阅读(175)  评论(0编辑  收藏  举报