首页 > 代码库 > 2017.3.4[hihocoder#1403]后缀数组一·重复旋律

2017.3.4[hihocoder#1403]后缀数组一·重复旋律

好久没发博了。

后缀数组板子题。具体实现就不解释了,hihocoder很良心。

http://hihocoder.com/problemset/problem/1403

技术分享
 1 #include<cmath>
 2 #include<queue>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define N 20010
10 #define RG register
11 #define inf 0x3f3f3f3f
12 #define Inf 99999999999999999LL
13 using namespace std;
14 typedef long long LL;
15 int h,k,n,t,ans,a[N],b[N],q[N],sa[N],ssa[N],cnta[N],cntb[N],heit[N],Rank[N],music[N];
16 inline int Abs(RG const int &a){return a>0?a:-a;}
17 inline int Max(RG const int &a,RG const int &b){return a>b?a:b;}
18 inline int Min(RG const int &a,RG const int &b){return a>b?b:a;}
19 inline int gi(){
20     RG int x=0;RG bool flag=0;RG char c=getchar();
21     while((c<0||c>9)&&c!=-) c=getchar();
22     if(c==-) c=getchar(),flag=1;
23     while(c>=0&&c<=9) x=x*10+c-0,c=getchar();
24     return flag?-x:x;
25 }
26 inline void getsa(){
27     for (int i=1;i<=n;++i)   ++cnta[music[i]];
28     for (int i=1;i<=100;++i) cnta[i]+=cnta[i-1];
29     for (int i=n;i;--i)      sa[cnta[music[i]]--]=i;
30     Rank[sa[1]]=1;
31     for (int i=2;i<=n;++i){
32         Rank[sa[i]]=Rank[sa[i-1]];
33         if(music[sa[i]]!=music[sa[i-1]])
34             ++Rank[sa[i]];
35     }
36     for (int now=1;Rank[sa[n]]<n;now<<=1){
37     memset(cnta,0,sizeof(cnta));
38     memset(cntb,0,sizeof(cntb));
39         for (int i=1;i<=n;++i){
40             ++cnta[a[i]=Rank[i]];                 //rank即为上一次排序好的第一关键字
41             ++cntb[b[i]=(i+now<=n)?Rank[i+now]:0];//rank[i+now]即为第二关键字
42         }
43         for (int i=1;i<=n;++i) cntb[i]+=cntb[i-1];
44         for (int i=n;i;--i)    ssa[cntb[b[i]]--]=i;//ssa即为按第二关键字排的“假”sa
45         for (int i=1;i<=n;++i) cnta[i]+=cnta[i-1];
46         for (int i=n;i;--i)    sa[cnta[a[ssa[i]]]--]=ssa[i];//相当于把i替换为ssa[i],从而达到双关键字排序的目的
47         Rank[sa[1]]=1;
48         for (int i=2;i<=n;++i){
49             Rank[sa[i]]=Rank[sa[i-1]];
50             if (a[sa[i]]!=a[sa[i-1]]||b[sa[i]]!=b[sa[i-1]]) ++Rank[sa[i]];
51         }
52     }
53     for (int i=1,j=0;i<=n;++i){
54         if(j) --j;
55         while (music[i+j]==music[sa[Rank[i]-1]+j]) ++j;
56         heit[Rank[i]]=j;
57     }
58 }   
59 inline void work(){
60     n=gi();k=gi();
61     if(k==1){
62     printf("%d\n",n);
63     return;
64     }
65     for (RG int i=1;i<=n;++i)
66     music[i]=gi();
67     getsa();
68     //for (RG int i=1;i<=n;++i) cout<<heit[i]<<‘ ‘;
69     //cout<<endl;
70     for (RG int i=1;i<=n;++i){
71     while(h<t&&heit[i]<heit[q[t]]) --t;
72     q[++t]=i;
73     //cout<<q[h+1]<<‘ ‘<<q[t]<<endl;
74     while(q[h+1]<=q[t]-k+1) ++h;
75     if(h<t) ans=Max(ans,heit[q[h+1]]);
76     //cout<<ans<<endl;
77     }
78     printf("%d\n",ans);
79 }
80 int main(){
81     work();
82     return 0;
83 }
View Code

 

2017.3.4[hihocoder#1403]后缀数组一·重复旋律