BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP
先建出广义后缀自动机。
然后跑出文章中每一个位置的最大匹配距离。
然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离。
显然可以二分$L$的取值。
然后容易得到$DP$方程
$f[i]=max(f[i-1],f[j]+i-j)(j<=i-L)$
然后就发现$j$属于一个区间,然后就可以单调队列优化了。
#include <map> #include <ctime> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 2200005 namespace SAM{ int last,cnt,go[maxn][2],l[maxn],fa[maxn],n,m,q; int f[maxn],que[maxn],hd,tl,d[maxn]; char s[maxn]; void init(){last=cnt=1;} void add(int x) { int q,p=last; if (q=go[p][x]) { if (l[q]==l[p]+1) last=q; else { int nq=last=++cnt; l[nq]=l[p]+1; memcpy(go[nq],go[q],sizeof go[q]); fa[nq]=fa[q];fa[q]=nq; for (;go[p][x]==q&&p;p=fa[p]) go[p][x]=nq; last=nq; } } else { int np=last=++cnt; l[np]=l[p]+1; for (;p&&!go[p][x];p=fa[p]) go[p][x]=np; if (!p) fa[np]=1; else { q=go[p][x]; if (l[q]==l[p]+1) fa[np]=q; else { int nq=++cnt;l[nq]=l[p]+1; memcpy(go[nq],go[q],sizeof go[q]); fa[nq]=fa[q]; fa[q]=fa[np]=nq; for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq; } } } } void ins() { last=1; scanf("%s",s+1); n=strlen(s+1); F(i,1,n) add(s[i]-'0'); } bool check(int mid) { f[0]=0; tl=0;hd=1; F(i,1,n) { f[i]=f[i-1];int p=i-mid; if (p>=0) { while (hd<=tl&&f[que[tl]]-que[tl]<f[i-mid]-p)tl--; que[++tl]=p; } while (hd<=tl&&que[hd]<i-d[i]) hd++; if (hd<=tl) f[i]=max(f[i],f[que[hd]]+i-que[hd]); } if (f *10>=n*9) return true; else return false; } void dp() { scanf("%s",s+1); n=strlen(s+1); memset(d,0,(n+1)*sizeof(int)); int now=1,t=0; F(i,1,n) { if (go[now][s[i]-'0']) now=go[now][s[i]-'0'],t++; else { while (now&&!go[now][s[i]-'0']) now=fa[now]; if (!now) now=1,t=0; else t=l[now]+1,now=go[now][s[i]-'0']; } d[i]=t; } int l=0,r=n; while (l<r) { int mid=(l+r)/2+1; if (check(mid)) l=mid; else r=mid-1; } printf("%d\n",l); } void solve() { init(); scanf("%d%d",&q,&m); F(i,1,m) ins(); F(i,1,q) dp(); } } int main() { using namespace SAM; solve(); }
- 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]Cheat 广义后缀自动机+二分+单调队列优化DP
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
- [后缀自动机][单调队列优化DP] BZOJ 2806: [Ctsc2012]Cheat
- [BZOJ2806][Ctsc2012][后缀自动机][队列优化][DP]Cheat
- [BZOJ2806] [CTSC2012] Cheat - 后缀自动机 - DP - 单调队列
- BZOJ.2806.[CTSC2012]Cheat(广义后缀自动机 DP 单调队列)
- bzoj 2806: [Ctsc2012]Cheat (后缀自动机+dp+单调队列)
- bzoj2806 【Ctsc2012】 Cheat 后缀自动机+单调队列优化dp
- bzoj2806 [Ctsc2012]Cheat(单调队列优化dp+二分+广义SAM)
- BZOJ2806 [Ctsc2012]Cheat 【后缀自动机 + 二分 + 单调队列优化DP】
- bzoj2806 [Ctsc2012]Cheat(后缀自动机+单调队列优化DP)
- bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP
- [BZOJ2806][Ctsc2012]Cheat(广义后缀自动机+dp)
- [BZOJ2806][Ctsc2012]Cheat && 后缀自动机
- 【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)