whu1564 求字符串的所有循环子串第k大 :后缀数组模板

原题少了当前的字符,不过并无差别

利用sa数组可以很方便的求出来==

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 struct SA{
 6   int sa[2000005],t[2000005],t2[2000005],c[2000005],n,m;
 7   void build_sa(char *s,int _n){
 8     n=2*_n+1; m=128;
 9     int i,*x=t,*y=t2;
10     //基数排序
11     for (i=0;i<m;i++) c[i]=0;
12     for (i=0;i<n;i++) c[x[i]=s[i]]++;
13     for (i=1;i<m;i++) c[i]+=c[i-1];
14     for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
15     for (int k=1;k<=n;k<<=1){
16         int p=0;
17         //直接利用sa数组排序第二关键字
18         for (i=n-k;i<n;i++) y[p++]=i;
19         for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k;
20         //基数排序第一关键字
21         for (i=0;i<m;i++) c[i]=0;
22         for (i=0;i<n;i++) c[x[y[i]]]++;
23         for (i=0;i<m;i++) c[i]+=c[i-1];
24         for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
25         //根据sa和y数组计算新的x数组
26         swap(x,y);
27         p=1; x[sa[0]]=0;
28         for (i=1;i<n;i++)
29   x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
30         if (p>=n) break;
31         m=p;//下次基数排序的最大值
32     }
33   }
34   int solve(int k){
35     int i,cnt=0;
36     for (i=0;i<n;i++)
37     {
38       if (sa[i]<=n/2&&sa[i]!=0) cnt++;
39       if (cnt==k) return sa[i];
40     }
41   }
42 }H;
43 char s[2000005];
44 int main()
45 {
46     int i,n,k;
47     while (~scanf("%d%d",&n,&k))
48     {
49       scanf("%s",s);
50       for (i=0;i<n;i++) s[i+n]=s[i]=s[i]-'0';
51       s[2*n]=10;
52       H.build_sa(s,n);
53       printf("%d\n",H.solve(k));
54     }
55     return 0;
56 }
View Code

题目链接:http://acm.whu.edu.cn/land/problem/detail?problem_id=1564

posted on 2015-04-28 11:25  xiao_xin  阅读(189)  评论(0编辑  收藏  举报

导航