[BZOJ2806]后缀自动机+DP

题面:http://www.lydsy.com/JudgeOnline/problem.php?id=2806

大神的题解:http://blog.csdn.net/acdreamers/article/details/10833181

不过维护单调队列的那一段好像错了?

AC代码:

#include
#include
#include
#include
#define M 2500010
#define N 5000010 
using namespace std;
int mx[M],f[M],q[M],n,m,ans;
char str[M];
struct Suffix_Automan{
	int root,cnt,last,ch[N][3],dep[N],fa[N];
	inline int newnode(int deep){
		dep[++cnt]=deep;
		return cnt;
	}
	void init(){
		last=root=cnt=1;
	}
	void ins(int x){
		int p=newnode(dep[last]+1);
		int u=last;
		for (;u&&!ch[u][x];u=fa[u]) ch[u][x]=p;
		if (!u) fa[p]=root;
		else {
			int q=ch[u][x];
			if (dep[q]==dep[u]+1) fa[p]=q;
			else{
				int nq=newnode(dep[u]+1);
				fa[nq]=fa[q];
				fa[q]=fa[p]=nq;
				memcpy(ch[nq],ch[q],sizeof(ch[nq]));
				for (;u&&ch[u][x]==q;u=fa[u]) ch[u][x]=nq;
			}
		}
		last=p;
	}
	void match(){
		int ro=root,tmp=0;
		for (int i=0;str[i];i++){
			int x=str[i]-'0';
			if (ch[ro][x]) tmp++,ro=ch[ro][x];
			else {
				for (;ro&&!ch[ro][x];ro=fa[ro]);
				if (ch[ro][x]) tmp=dep[ro]+1,ro=ch[ro][x];
				else tmp=0,ro=root;
			}
			mx[i+1]=tmp;
		}
	}
	bool judge(int lmt,int len){
		int he,ta,r;
		f[0]=q[ta=0]=0;
		he=ta+1;
		for (int i=1;i<=len;i++){
			f[i]=f[i-1],r=i-lmt;
			if (r>=0){
				for (;he<=ta&&f[r]-r>f[q[ta]]-q[ta];ta--);
				q[++ta]=r;
			}
			while (he<=ta&&q[he]=len*9;
	}
}SAM;
inline int getstr(){
	int len=0;
	while (!isdigit((str[len]=getchar())));
	len++;
	while (isdigit((str[len++]=getchar())));
	str[--len]=0;
	return len; 
}
int main(){
	scanf("%d%d",&n,&m);
	SAM.init();
	for (;m;m--){
		getstr();
		for (int i=0;str[i];i++) SAM.ins(str[i]-'0');
		SAM.ins(2);
	}
	for (;n;n--){
		int len=getstr();
		SAM.match();
		int l=0,r=len;
		ans=0;
		while (l<=r){
			int mid=(l+r)>>1;
			if (SAM.judge(mid,len)){
				l=mid+1;
				ans=mid;
			}
			else r=mid-1;
		}
		printf("%d\n",ans);
	}
} 


你可能感兴趣的:(模版,单调队列,字符串,后缀自动机)