[CTSC2012]熟悉的文章
阿新 • • 發佈:2019-02-08
題意
有多個主串,每次詢問將詢問串分成多個連續子串,如果一個子串長度且在主串中出現過就是合法的
如果合法的子串總長度詢問串長的,這個串就是合法的字串,求使得詢問串成為合法的字串的最大的
題解
先建好廣義發現滿足單調性,所以可以二分答案
考慮怎麼用dp啊
考慮一個暴力的表示前個字元最長合法長度,表示匹配到的最長公共子串長度(在廣義上,求法同)
可以發現單調遞增的,是單調不增的,所以可以使用單調佇列優化到
#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1 ,C+1,stdout),C=-1;}
template<class T>inline void we(T x){
if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e6+5,M=2*N;
typedef long long ll;
typedef int arr[M];
struct SAM{
int las,T,ch[M][2];arr fa,len;
SAM(){las=T=1;}
inline void ins(int c){
int p=las,np;fa[las=np=++T]=1,len[np]=len[p]+1;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
if(p){
int q=ch[p][c],nq;
if(len[p]+1==len[q])fa[np]=q;
else{
fa[nq=++T]=fa[q],len[nq]=len[p]+1,memcpy(ch[nq],ch[q],4*2);
for(fa[q]=fa[np]=nq;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
}
}
}
int n,mac[N],f[N],q[N];char s[N];
inline void Match(){
int x=1,l=0,c;
fp(i,1,n){
c=s[i]-'0';while(x&&!ch[x][c])x=fa[x],l=len[x];
if(x)x=ch[x][c],++l;else x=1,l=0;mac[i]=l;
}
}
inline bool chk(int L){
int h=1,t=0;
fp(i,1,L-1)f[i]=0;
fp(i,L,n){f[i]=f[i-1];
while(h<=t&&f[q[t]]-q[t]<f[i-L]-(i-L))--t;
q[++t]=i-L;while(h<=t&&q[h]<i-mac[i])++h;
if(h<=t)cmax(f[i],f[q[h]]+i-q[h]);
}
return f[n]*10>=n*9;
}
inline void sol(){
scanf("%s",s+1);n=strlen(s+1);Match();
int L=0,R=n,ans=0,mid;
while(L<=R){
mid=(L+R)>>1;
if(chk(mid))ans=mid,L=mid+1;
else R=mid-1;
}
printf("%d\n",ans);
}
}p;
int n,m;char s[N];
int main(){
#ifndef ONLINE_JUDGE
file("s");
#endif
scanf("%d%d",&n,&m);
fp(i,1,m){
scanf("%s",s),p.las=1;
fp(j,0,strlen(s)-1)p.ins(s[j]-'0');
}
while(n--)p.sol();
return Ot(),0;
}