【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)
2018-03-13 20:24
471 查看
【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)
题面
BZOJ洛谷
题解
很有趣的一道题啊对于在所有的串上面进行匹配?
很明显的后缀自动机
所以先构建出广义后缀自动机
然后这个拆分很像一个\(dp\)
同时,要求的东西很像一个可以二分的样子
所以二分一个答案,考虑如何\(dp\)
设\(f[i]\)表示处理完前\(i\)个字符,能够匹配上的最多的字符个数
转移是\(f[i]=max(f[j]+i-j)\),满足\(i-j>mid\)
同时\(S[j+1..i]\)能够匹配上
因此,可以提前预处理出每个位置能够匹配上的最大长度
然后利用单调队列进行转移就行啦
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ll long long #define RG register #define MAX 1111111 inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Node { int son[2]; int ff,len; }t[MAX]; char ch[MAX]; int p[MAX],f[MAX]; int last=1,tot=1; int Q[MAX],H,T; int n,m; void extend(int c) { int p=last,np=++tot;last=np; t[np].len=t[p].len+1; while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff; if(!p)t[np].ff=1; else { int q=t[p].son[c]; if(t[q].len==t[p].len+1)t[np].ff=q; else { int nq=++tot; t[nq]=t[q]; t[nq].len=t[p].len+1; t[q].ff=t[np].ff=nq; while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff; } } } void pre() { int len=strlen(ch+1); int now=1,ml=0; for(int i=1;i<=len;++i) { int c=ch[i]-48; if(t[now].son[c])now=t[now].son[c],ml+=1; else { while(now&&!t[now].son[c])now=t[now].ff; if(!now)ml=0,now=1; else ml=t[now].len+1,now=t[now].son[c]; } p[i]=ml; } } bool check(int k) { int l=strlen(ch+1); H=1;T=0; for(int i=1;i<=l;++i) { f[i]=f[i-1]; if(i<k)continue; while(H<=T&&f[Q[T]]-Q[T]<=f[i-k]-i+k)--T; Q[++T]=i-k; while(H<=T&&Q[H]<i-p[i])++H; if(H<=T)f[i]=max(f[i],f[Q[H]]+i-Q[H]); } return f[l]*10>=l*9; } int main() { n=read();m=read(); while(m--) { last=1; scanf("%s",ch+1); for(int i=1,l=strlen(ch+1);i<=l;++i)extend(ch[i]-48); } while(n--) { scanf("%s",ch+1); int len=strlen(ch+1); pre(); int l=1,r=len,ans=0; while(l<=r) { int mid=(l+r)>>1; if(check(mid))ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); } return 0; }
相关文章推荐
- 【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)
- [二分 后缀自动机 单调队列优化DP] BZOJ 2806 [Ctsc2012]Cheat
- 【bzoj2806】[Ctsc2012]Cheat 广义后缀自动机+二分+单调队列优化dp
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
- 【BZOJ2806】[Ctsc2012]Cheat 广义后缀自动机+二分+单调队列优化DP
- bzoj 2806: [Ctsc2012]Cheat (后缀自动机+dp+单调队列)
- bzoj 2806 [Ctsc2012]Cheat 后缀自动机 单调队列优化dp
- [BZOJ2806] [CTSC2012] Cheat - 后缀自动机 - DP - 单调队列
- BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP
- [BZOJ2806][Ctsc2012]Cheat(后缀自动机+单调队列优化dp)
- [后缀自动机][单调队列优化DP] BZOJ 2806: [Ctsc2012]Cheat
- BZOJ.2806.[CTSC2012]Cheat(广义后缀自动机 DP 单调队列)
- BZOJ 2806: [Ctsc2012]Cheat 后缀自动机+单调队列优化DP
- BZOJ2806 [Ctsc2012]Cheat 【后缀自动机 + 二分 + 单调队列优化DP】
- [BZOJ2806][Ctsc2012][后缀自动机][队列优化][DP]Cheat
- bzoj2806 [Ctsc2012]Cheat(单调队列优化dp+二分+广义SAM)
- bzoj2806 [Ctsc2012]Cheat(后缀自动机+单调队列优化DP)
- bzoj2806 【Ctsc2012】 Cheat 后缀自动机+单调队列优化dp
- BZOJ 2806 Cheat (后缀自动机+dp)
- BZOJ_1044_[HAOI2008]木棍分割_二分答案+DP+单调队列