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) 显然单调队列乱搞一下就行了。
题解:对所有串建一个广义后缀自动机,然后对于每个模板串算出到第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; }
相关文章推荐
- 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(后缀自动机,二分答案,动态规划,单调队列)