POJ 3261 后缀数组

题意:

最长的出现k次的重复(可重叠)子串

 

题解:

和POJ 1743一样,稍作改变,求最大的话一般都是对后缀数组二分处理。。

http://www.cnblogs.com/proverbs/archive/2013/02/05/2893419.html

判定条件从位置相差>=m改为是否存在一个块内后缀的个数大于等于m

 


数比较大,快排搞定,好像基数排序也可以。

 

View Code
 1 #include <iostream>

 2 #include <cstring>

 3 #include <cstdio>

 4 #include <cstdlib>

 5 #include <algorithm>

 6 

 7 #define N 50500

 8 

 9 using namespace std;

10 

11 int r[N],wa[N],wc[N],wv[N],sa[N],wb[N],height[N],rank[N];

12 int n,m;

13 

14 inline bool cmp1(int a,int b)

15 {

16     if(r[a]==r[b]) return a<b;

17     return r[a]<r[b];

18 }

19 

20 inline bool cmp2(int a,int b)

21 {

22     if(wv[a]==wv[b]) return a<b;

23     return wv[a]<wv[b];

24 }

25 

26 inline bool cmp(int *r,int a,int b,int l)

27 {

28     return r[a]==r[b]&&r[a+l]==r[b+l];

29 }

30 

31 inline void da(int *r,int *sa,int n,int m)

32 {

33     int i,j,p,*x=wa,*y=wb,*t;

34     for(i=0;i<n;i++) wc[i]=i,x[i]=r[i];

35     sort(wc,wc+n,cmp1);

36     for(i=0;i<n;i++) sa[i]=wc[i];

37     for(j=1,p=1;p<n;j<<=1,m=p)

38     {

39         for(i=n-j,p=0;i<n;i++) y[p++]=i;

40         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;

41         for(i=0;i<n;i++) wv[i]=x[y[i]];

42         for(i=0;i<n;i++) wc[i]=i;

43         sort(wc,wc+n,cmp2);

44         for(i=0;i<n;i++) sa[i]=y[wc[i]];

45         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=0;i<n;i++)

46             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;

47     }

48 }

49 

50 inline void getheight(int *r,int *sa,int n)

51 {

52     int i,j,k=0;

53     for(i=1;i<=n;i++) rank[sa[i]]=i;

54     for(i=0;i<n;height[rank[i++]]=k)

55         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);

56 }

57 

58 inline bool check(int x)

59 {

60     int cnt=1;

61     for(int i=1;i<=n;i++)

62     {

63         if(height[i]<x) cnt=1;

64         else cnt++;

65         if(cnt>=m) return true;

66     }

67     return false;

68 }

69 

70 inline void getans()

71 {

72     int l=1,r=n,mid,res;

73     while(l<=r)

74     {

75         mid=(l+r)>>1;

76         if(check(mid)) res=mid,l=mid+1;

77         else r=mid-1;

78     }

79     printf("%d\n",res);

80 }

81 

82 inline void go()

83 {

84     for(int i=0;i<n;i++) scanf("%d",&r[i]);

85     r[n]=0;

86     da(r,sa,n+1,1000010);

87     getheight(r,sa,n);

88     getans();

89 }

90 

91 int main()

92 {

93     while(scanf("%d%d",&n,&m)!=EOF) go();

94     return 0;

95 }

 

 

你可能感兴趣的:(后缀数组)