luogu2852 [USACO06DEC]牛奶模式Milk Patterns

参考那篇经典论文。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n, k, r[20005], x[20005], y[20005], sa[20005], rank[20005], hei[20005];
int m=1000005, c[1000005], p, ans=0;
void getSa(){
	r[n++] = 0;
	for(int i=0; i<m; i++)	c[i] = 0;
	for(int i=0; i<n; i++)	c[x[i]=r[i]]++;
	for(int i=1; i<m; i++)	c[i] += c[i-1];
	for(int i=n-1; i>=0; i--)	sa[--c[x[i]]] = i;
	for(int j=1; p<n; j*=2, m=p){
		p = 0;
		for(int i=n-j; i<n; i++)	y[p++] = i;
		for(int i=0; i<n; i++)	if(sa[i]>=j)	y[p++] = sa[i] - j;
		for(int i=0; i<m; i++)	c[i] = 0;
		for(int i=0; i<n; i++)	c[x[y[i]]]++;
		for(int i=1; i<m; i++)	c[i] += c[i-1];
		for(int i=n-1; i>=0; i--)	sa[--c[x[y[i]]]] = y[i];
		swap(x, y);
		x[sa[0]] = 0;
		p = 1;
		for(int i=1; i<n; i++)
			if(y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j])
				x[sa[i]] = p - 1;
			else
				x[sa[i]] = p++;
	}
	n--;
}
void getLcp(){
	int h=0;
	for(int i=1; i<=n; i++)	rank[sa[i]] = i;
	for(int i=0; i<n; i++){
		if(h)	h--;
		int j=sa[rank[i]-1];
		while(r[i+h]==r[j+h])	h++;
		hei[rank[i]] = h;
	}
}
bool check(int lim){
	int cnt=0;
	for(int i=1; i<=n; i++){
		if(hei[i]<lim)	cnt = 0;
		else{
			cnt++;
			if(cnt>=k)	return true;
		}
	}
	return false;
}
void getAns(){
	int l=1, r=n, mid;
	while(l<=r){
		mid = (l + r) / 2;
		if(check(mid)){
			ans = mid;
			l = mid + 1;
		}
		else	r = mid - 1;
	}
}
int main(){
	cin>>n>>k;
	k--;
	for(int i=0; i<n; i++)	scanf("%d", &r[i]), r[i]++;
	getSa();
	getLcp();
	getAns();
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/8260749.html