您的位置:首页 > 其它

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

2017-05-25 20:28 393 查看
题意:算了不想写题意了233

题解:对所有串建一个广义后缀自动机,然后对于每个模板串算出到第i位最大能匹配多远,二分出一个答案,然后写出一个DP方程,F[i]表示到第i位最多能匹配多少位,f[i]=max(f[j] (i-maxx[i]<=j<=i-midans) +i-j) 显然单调队列乱搞一下就行了。

#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
#define eps 1e-8
int n,m;
char s[2000000];
struct sam
{
sam *son[2];
sam *parent;
int max_len;
sam(int _):max_len(_)
{
son[0]=son[1]=parent=0x0;
}
}*root=new sam(0),*last=root;
void Insert(int zm)
{
sam *p=last;
sam *np=new sam(p->max_len+1);
while(p && !p->son[zm])
{
p->son[zm]=np;
p=p->parent;
}
if(!p) np->parent=root;
else
{
sam *q=p->son[zm];
if(q->max_len==p->max_len+1) np->parent=q;
else
{
sam *nq=new sam(p->max_len+1);
nq->parent=q->parent;
memcpy(nq->son,q->son,sizeof(nq->son));
np->parent=nq;
q->parent=nq;
while(p && p->son[zm]==q) p->son[zm]=nq,p=p->parent;
}
}
last=np;
}
int maxx[2000000];
int f[2000000];
int len;
struct point
{
int id,val;
point(){}
point(int _,int __):id(_),val(__){}
};
bool check(int k)
{
static point q[2000000];
int s=1,t=1;
for(int i=0;i<k;i++) f[i]=0;
for(int i=k;i<=len;i++)
{
while(s<t && f[i-k]-(i-k)>q[t-1].val) t--;
q[t++]=point(i-k,f[i-k]-(i-k));
f[i]=f[i-1];
while(s<t && i-q[s].id>maxx[i]) s++;
if(s<t) f[i]=max(f[i],q[s].val+i);
}
double rate=f[len];
rate/=(double)len;
return rate>=0.9-eps;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%s",s+1);
len=strlen(s+1);
last=root;
for(int j=1;j<=len;j++) Insert(s[j]-'0');
}
for(int hh=1;hh<=n;hh++)
{
scanf("%s",s+1);
len=strlen(s+1);
int fix=0;
sam *o=root;
for(int i=1;i<=len;i++)
{
if(o->son[s[i]-'0']) o=o->son[s[i]-'0'],fix++;
else
{
while(o && !o->son[s[i]-'0']) o=o->parent;
if(!o)
{
fix=0;
o=root;
}
else
{
fix=o->max_len;
o=o->son[s[i]-'0'];
fix++;
}
}
maxx[i]=fix;
}
int jilu=0;
int l=1,r=len;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) jilu=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",jilu);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: