您的位置:首页 > 其它

BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP

2017-04-27 20:21 585 查看

先建出广义后缀自动机。

然后跑出文章中每一个位置的最大匹配距离。

然后定义$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

[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(); }

[p]  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: