[bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组_二分答案

Milk Patterns 产奶的模式 bzoj-1717 Usaco-2006 Dec

题目大意:给定一个字符串,求最长的至少出现了$k$次的子串长度。

注释:$1\le n\le 2\cdot 10^4$,$2\le k\le n$。


想法:不难想到二分答案,现在我们考虑如何验证。

这里就是后缀数组的一个妙用了。

我们对原串建立后缀数组,观察$ht$数组。

考虑当前二分出来的$mid$。如果有至少连续$k$的$ht$值都不小于$mid$,那么$k$就是合法的。

故此我们直接扫$ht$数组看看最长的连续比$mid$大的$ht$有多少个即可。

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010 
using namespace std;
int wv[N],wa[N],sa[N],Ws[N],wb[N],t[N],rk[N],ht[N],r[N];
int n,m=1000009;
inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
void build_sa()
{
	int i,j,p,*x=wa,*y=wb,*t;
	for(i=0;i<m;i++) Ws[i]=0;
	for(i=0;i<n;i++) Ws[x[i]=r[i]]++;
	for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
	for(i=n-1;~i;i--) sa[--Ws[x[i]]]=i;
	for(p=j=1;p<n;j<<=1,m=p)
	{
		for(p=0,i=n-j;i<n;i++) y[p++]=i;
		for(i=0;i<n;i++) if(sa[i]-j>=0) y[p++]=sa[i]-j;
		for(i=0;i<n;i++) wv[i]=x[y[i]];
		for(i=0;i<m;i++) Ws[i]=0;
		for(i=0;i<n;i++) Ws[wv[i]]++;
		for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
		for(i=n-1;~i;i--) sa[--Ws[wv[i]]]=y[i];
		for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++)
		{
			if(y[sa[i]]==y[sa[i-1]]&&y[sa[i-1]+j]==y[sa[i]+j]) x[sa[i]]=p-1;
			else x[sa[i]]=p++;
		}
	}
	for(i=1;i<n;i++) rk[sa[i]]=i;
	for(i=p=0;i<n-1;ht[rk[i++]]=p)
		for(p?p--:0,j=sa[rk[i]-1];r[i+p]==r[j+p];p++);
}
template <typename T> void Max(T &x,T y) {x=max(x,y);}
// inline void Max(int &x,int y) {x=max(x,y);}
int check(int x)
{
	int re=-1,now=0;
	for(int i=0;i<n;i++)
	{
		if(ht[i]>=x) now++;
		else Max(re,now),now=1;
	}
	Max(re,now);
	return re;
}
int main()
{
	n=rd();int k=rd(); for(int i=0;i<n;i++) r[i]=rd();
	r[n++]=0; build_sa();
	int l=0,r=n+1;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(check(mid)>=k) l=mid+1;
		else r=mid;
	}
	l--;
	cout << l << endl ;
	return 0;
}

小结:后缀数组有很多特别有趣的妙用,要多积累啊!因为开$iostream$的缘故所以不能有变量叫做$ws$,我就叫$Ws$了……

posted @ 2018-12-12 19:35  JZYshuraK_彧  阅读(135)  评论(0编辑  收藏  举报