luogu P2852 [USACO06DEC]Milk Patterns G
容易发现这就是后缀排序后连续 \(k\) 个后缀的 \(lcp\) 的最小值的最大值,用单调队列跑一遍 \(height\) 数组即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<deque>
using namespace std;
const int N=20009;
deque <int> q;
int n,k,a[N],b[N],m;
struct Suffix_Array
{
int s[N],x[N],y[N],c[N],sa[N],height[N],h[N],n,m;
void Rsort()
{
for (int i=1;i<=m;i++) c[i]=0;
for (int i=1;i<=n;i++) c[x[y[i]]]++;
for (int i=1;i<=m;i++) c[i]+=c[i-1];
for (int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i];
}
void Get_SA()
{
m=122;
for (int i=1;i<=n;i++)
x[i]=s[i],y[i]=i;
Rsort();
for (int k=1;k<=n;k<<=1)
{
int num=0;
for (int i=n-k+1;i<=n;i++)
y[++num]=i;
for (int i=1;i<=n;i++)
if(sa[i]>k)
y[++num]=sa[i]-k;
Rsort(),swap(x,y);
x[sa[1]]=num=1;
for (int i=2;i<=n;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
if(num==n) break;
m=num;
}
}
void Get_Height()
{
for (int i=1;i<=n;i++)
{
int t=max(h[i-1]-1,0),j,k;
for (j=i+t,k=sa[x[i]-1]+t;s[j]==s[k]&&j<=n&&k<=n;j++,k++);
h[i]=j-i;
}
for (int i=1;i<=n;i++)
height[i]=h[sa[i]];
}
void work()
{
Get_SA(),Get_Height();
}
}A;
void init()
{
scanf("%d %d",&n,&k);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+1+n);
m=unique(b+1,b+1+n)-(b+1);
for (int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+1+m,a[i])-b;
}
int Get_Ans()
{
if(k==1) return n;
if(k>n) return 0;
k--;
for (int i=2;i<=k+1;i++)
{
while(!q.empty()&&A.height[i]<=A.height[q.back()])
q.pop_back();
q.push_back(i);
}
int ans=A.height[q.front()];
for (int i=k+2;i<=n;i++)
{
while(!q.empty()&&i-q.front()>=k)
q.pop_front();
while(!q.empty()&&A.height[i]<=A.height[q.back()])
q.pop_back();
q.push_back(i);
ans=max(ans,A.height[q.front()]);
}
return ans;
}
void work()
{
A.n=n;
for (int i=1;i<=n;i++)
A.s[i]=a[i];
A.work();
printf("%d\n",Get_Ans());
}
int main()
{
init();
work();
return 0;
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!