bzoj 2806 [Ctsc2012]Cheat 后缀自动机 单调队列优化dp
2016-10-24 10:58
435 查看
首先把字典中所有的串接在一起,两两间用非法字符隔开,跑一个后缀自动机(感觉这样比广义后缀自动机好写一些?)
然后对于要匹配的串在后缀自动机里跑一遍得到每个点向前能匹配的最大长度v[i]。
求的东西可以二分答案。
然后dp,设f[i]表示到i能匹配上的所有子串最大长度。
f[i]=⎧⎩⎨max(f[i],f[j])(j∈[0,i−1])max(f[i],f[j]+v[i])(j∈[0,i−v[i]])max(f[i],f[j]−j+i)(j∈[i−v[i]+1,i−x])
其中前两段维护一个前缀和就行了。
第三段维护一个关于f[i]-i 的单调队列。
然后对于要匹配的串在后缀自动机里跑一遍得到每个点向前能匹配的最大长度v[i]。
求的东西可以二分答案。
然后dp,设f[i]表示到i能匹配上的所有子串最大长度。
f[i]=⎧⎩⎨max(f[i],f[j])(j∈[0,i−1])max(f[i],f[j]+v[i])(j∈[0,i−v[i]])max(f[i],f[j]−j+i)(j∈[i−v[i]+1,i−x])
其中前两段维护一个前缀和就行了。
第三段维护一个关于f[i]-i 的单调队列。
#include <bits/stdc++.h> using namespace std; #define N 1100000 int n,m,ln,h,r; char s ; int v ,f ,sum ,q ; struct SAM { int trs[N<<1][3],fa[N<<1],len[N<<1],cnt,last; void init(){cnt=1;last=1;} void insert(int x) { int p=last,np=++cnt,q,nq; last=np;len[np]=len[p]+1; for(;p&&!trs[p][x];p=fa[p])trs[p][x]=np; if(!p)fa[np]=1; else { q=trs[p][x]; if(len[q]==len[p]+1)fa[np]=q; else { fa[nq=++cnt]=fa[q]; len[nq]=len[p]+1; memcpy(trs[nq],trs[q],sizeof(trs[q])); fa[q]=fa[np]=nq; for(;p&&trs[p][x]==q;p=fa[p])trs[p][x]=nq; } } } void solve() { int now=1,cnt=0; for(int i=1;i<=ln;i++) { int t=s[i]-'0'; if(trs[now][t]) now=trs[now][t],cnt++; else { for(;now&&!trs[now][t];now=fa[now]); if(!now)now=1,cnt=0; else cnt=len[now]+1,now=trs[now][t]; } v[i]=cnt; } } }sam; int check(int x) { h=1;r=0;f[0]=0;sum[0]=0; for(int i=1;i<=ln;i++) { while(h<=r&&q[h]<=i-v[i])h++; f[i]=sum[i-1]; if(v[i]>=x) { if(h<=r)f[i]=max(f[i],f[q[h]]+(i-q[h])); f[i]=max(f[i],sum[i-v[i]]+v[i]); } sum[i]=max(sum[i-1],f[i]); if(i-x+1>=0) { while(h<=r&&f[q[r]]-q[r]<=f[i-x+1]-(i-x+1))r--; q[++r]=i-x+1; } } return f[ln]+(1e-8)>=(long double)ln*0.9; } int main() { //freopen("tt.in","r",stdin); sam.init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%s",s+1); ln=strlen(s+1); for(int j=1;j<=ln;j++) sam.insert(s[j]-'0'); sam.insert(2); } for(int i=1;i<=n;i++) { scanf("%s",s+1); ln=strlen(s+1); sam.solve(); int l=1,r=ln; while(l<=r) { int mid=(l+r)>>1; if(check(mid))l=mid+1; else r=mid-1; } printf("%d\n",r); } return 0; }
相关文章推荐
- [后缀自动机][单调队列优化DP] BZOJ 2806: [Ctsc2012]Cheat
- BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP
- 【bzoj2806】[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
- [BZOJ2806][Ctsc2012][后缀自动机][队列优化][DP]Cheat
- BZOJ.2806.[CTSC2012]Cheat(广义后缀自动机 DP 单调队列)
- bzoj 2806: [Ctsc2012]Cheat (后缀自动机+dp+单调队列)
- [BZOJ2806] [CTSC2012] Cheat - 后缀自动机 - DP - 单调队列
- bzoj2806 [Ctsc2012]Cheat(后缀自动机+单调队列优化DP)
- bzoj2806 【Ctsc2012】 Cheat 后缀自动机+单调队列优化dp
- bzoj2806 [Ctsc2012]Cheat(单调队列优化dp+二分+广义SAM)
- BZOJ2806 [Ctsc2012]Cheat 【后缀自动机 + 二分 + 单调队列优化DP】
- bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP
- [BZOJ2806][Ctsc2012]Cheat(广义后缀自动机+dp)
- [BZOJ2806][Ctsc2012]Cheat && 后缀自动机
- 【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)