# BZOJ2806_Cheat

Ctsc2012的题目。做完感觉自己瞬间变高富帅了。

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 2502000
using namespace std;

int next[maxn][3],pre[maxn],step[maxn];
int p,q,np,nq,cur,len,L;
int f[maxn];
int N,last,n,m;
int Q[maxn],bot,top;
char s[maxn];

void insert(int x)
{
np=++N,p=last,step[np]=step[p]+1,last=np;
for (; p!=-1 && next[p][x]==0; p=pre[p]) next[p][x]=np;
if (p==-1) return;
q=next[p][x];
if (step[q]==step[p]+1) { pre[np]=q; return; }
nq=++N,step[nq]=step[p]+1,pre[nq]=pre[q];
for (int i=0; i<3; i++) next[nq][i]=next[q][i];
pre[np]=pre[q]=nq;
for (; p!=-1 && next[p][x]==q; p=pre[p]) next[p][x]=nq;
}

bool check(int limit)
{
bot=1,top=0,f[0]=cur=len=0;
for (int i=1; s[i]; i++)
{
f[i]=f[i-1];
int k=s[i]-'0';
for (; cur!=-1 && next[cur][k]==0; cur=pre[cur]) ;
if (cur==-1) { cur=len=0; }
len=min(len,step[cur])+1;//当前状态的最大匹配长度
cur=next[cur][k];

p=i-limit;
if (p>=0)
{
while (bot<=top && Q[top]-f[Q[top]]>p-f[p]) top--;
Q[++top]=p;
}
while (bot<=top && Q[bot]<i-len) bot++;
if (bot<=top) f[i]=max(f[i],f[Q[bot]]+i-Q[bot]);

}
return f[L]*10>=L*9;
}

int main()
{
pre[0]=-1;
scanf("%d%d",&n,&m);
while (m--)
{
scanf("%s",s);
for (int i=0; s[i]; i++) insert(s[i]-'0');
insert(2);
}
while (n--)
{
scanf("%s",s+1);
L=strlen(s+1);
int l=0,r=L,mid;
while (l<r)
{
mid=(l+r+1)/2;
if (check(mid)) l=mid;
else r=mid-1;
}
printf("%d\n",l);
}
return 0;
}


posted @ 2014-06-24 15:18  092000  阅读(1882)  评论(0编辑  收藏  举报