# bzoj2806 [Ctsc2012]Cheat（SAM+单调队列优化dp）

f[i]=max{f[i1],f[j]+ij|ilen[i]<=j<=iL}$f[i]=max\{f[i-1],f[j]+i-j| i-len[i]<=j<=i-L\}$
j的取值范围是随着i的增大而单调右移的，因此可以单调队列优化到O(n)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define N 1000010
#define ll long long
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n=0,m,last,rt,par[N<<1],mx[N<<1],son[N<<1][2],len[N],f[N],qq[N];
char s[N];
inline void ins(int ch){
int p=last;
if(son[p][ch]){
int q=son[p][ch];
if(mx[q]==mx[p]+1){last=q;return;}
int nq=++n;mx[nq]=mx[p]+1;last=nq;par[nq]=par[q];par[q]=nq;
memcpy(son[nq],son[q],sizeof(son[q]));
for(;p&&son[p][ch]==q;p=par[p]) son[p][ch]=nq;return;
}int np=++n;mx[np]=mx[p]+1;last=np;
for(;p&&!son[p][ch];p=par[p]) son[p][ch]=np;
if(!p){par[np]=rt;return;}
int q=son[p][ch];
if(mx[q]==mx[p]+1){par[np]=q;return;}
int nq=++n;mx[nq]=mx[p]+1;memcpy(son[nq],son[q],sizeof(son[q]));
par[nq]=par[q];par[q]=par[np]=nq;
for(;p&&son[p][ch]==q;p=par[p]) son[p][ch]=nq;
}
inline int gao(){
int p=rt,sum=0,res=0;
for(int i=1;i<=m;++i){
int ch=s[i]-'0';
if(son[p][ch]) p=son[p][ch],++sum;
else{
while(p&&!son[p][ch]) p=par[p];
if(!p) p=rt,sum=0;
else sum=mx[p]+1,p=son[p][ch];
}len[i]=sum;res=max(res,len[i]);
}return res;
}
inline bool jud(int L){
int qh=1,qt=0;f[0]=0;
for(int i=1;i<=m;++i){
int j=i-L;
if(j>=0){
while(qh<=qt&&f[qq[qt]]-qq[qt]<=f[j]-(j)) --qt;
qq[++qt]=j;
}while(qh<=qt&&qq[qh]<i-len[i]) ++qh;f[i]=f[i-1];
if(qh<=qt) f[i]=max(f[i],f[qq[qh]]-qq[qh]+i);
}return f[m]*10>=m*9;
}
int main(){
//  freopen("a.in","r",stdin);
while(n2--){
scanf("%s",s+1);m=strlen(s+1);last=rt;
for(int i=1;i<=m;++i) ins(s[i]-'0');
}while(n1--){
scanf("%s",s+1);m=strlen(s+1);
int l=1,r=gao();
while(l<=r){
int mid=l+r>>1;
if(jud(mid)) l=mid+1;
else r=mid-1;
}printf("%d\n",l-1);
}return 0;
}