bzoj2806 【Ctsc2012】 Cheat 后缀自动机+单调队列优化dp
来源:互联网 发布:计天数的软件 编辑:程序博客网 时间:2024/05/22 07:02
题目大意:
给定一些标准串。
给定一个串,要求一个L使得在这个序列中可以取出若干个长度超过L的子串(这些子串必须是给定标准串的子串),且取出的串的总长度超过整个串的90%。
求最大的L。
题目分析:
先用后缀自动机求出以每个位置为结尾往前最多能匹配多少位,我们用数组a[i]来存储这个值。
这个只要对于所有的标准串建一个广义的后缀自动机,然后把这个串放进去跑一遍,如果能匹配的话,这一位就比上一位多匹配一位,否则跳parent,并且将当前匹配上的最大长度设为当前节点的max_len再继续匹配(详见代码。
然后我们要求L最小值最大,这种问题可以想到二分。
问题转化成了给定L,求是否能取出大于等于90%的子串使之满足条件。
这样我们设f[i]表示匹配到第i个位置匹配不上的字符有多少个。
那么转移很显然就是Min{f[i-1]+1,f[(i-a[i])~f[i-L]]};
这样的话我们很显然有一个时间复杂度上界是n^2的判定方法。
这样的时间复杂度不能接受,但是我们可以发现,i-a[i]是单调递增的,i-L也是单调递增的,那么我们可以用一个单调队列来维护这个这个这个值。
这样时间复杂度就降到了O(n)
算上二分,O(nlog(n))
代码如下:
#include <cstdio>#include <cstring>#include <algorithm>#define N 1200000using namespace std;int n,m;int len;char s[N];int f[N],a[N],dl[N];struct SAM{ SAM *son[2],*fa; int max_len; SAM(int _):max_len(_) { memset(son,0,sizeof(son)); fa=NULL; }}*root=new SAM(0),*last=root;void extend(int x){ SAM *p=last; SAM *np=new SAM(p->max_len+1); while(p && !p->son[x]) p->son[x]=np,p=p->fa; if(!p) np->fa=root; else { SAM *q=p->son[x]; if(p->max_len+1==q->max_len) np->fa=q; else { SAM *nq=new SAM(p->max_len+1); nq->fa=q->fa; memcpy(nq->son,q->son,sizeof(nq->son)); q->fa=nq; np->fa=nq; for(;p && p->son[x]==q;p=p->fa) p->son[x]=nq; } } last=np;}bool check(int L){ int l=1,r=0; f[0]=0; for(int i=1;i<=len;i++) { f[i]=f[i-1]+1; if(i-L>=0) { while(r>=l && f[i-L]<=f[dl[r]]) r--; dl[++r]=i-L; } while(r>=l && dl[l]<i-a[i]) l++; if(r>=l) f[i]=min(f[i],f[dl[l]]); } return f[len]*10<=len;}int main(){ scanf("%d%d",&n,&m); while(m--) { last=root; scanf("%s",s); for(int i=0;s[i];i++) extend(s[i]-'0'); } while(n--) { scanf("%s",s+1); len=strlen(s+1); int now=0,x; SAM *c=root; for(int i=1;i<=len;i++) { x=s[i]-'0'; while(c!=root && !c->son[x]) { now=c->fa->max_len; c=c->fa; } if(c->son[x]) { c=c->son[x]; now++; } a[i]=now; } int l=0,r=len,ans=0; while(l<=r) { int mid=l+r>>1; if(check(mid)) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); } return 0;}
阅读全文
0 0
- bzoj2806 【Ctsc2012】 Cheat 后缀自动机+单调队列优化dp
- [BZOJ2806] [CTSC2012] Cheat - 后缀自动机 - DP - 单调队列
- [BZOJ2806][Ctsc2012][后缀自动机][队列优化][DP]Cheat
- bzoj 2806 [Ctsc2012]Cheat 后缀自动机 单调队列优化dp
- BZOJ 2806: [Ctsc2012]Cheat 后缀自动机+单调队列优化DP
- [后缀自动机][单调队列优化DP] BZOJ 2806: [Ctsc2012]Cheat
- [BZOJ2806][Ctsc2012]Cheat && 后缀自动机
- bzoj 2806: [Ctsc2012]Cheat (后缀自动机+dp+单调队列)
- bzoj2806 Cheat 后缀自动机&单调队列
- [二分 后缀自动机 单调队列优化DP] BZOJ 2806 [Ctsc2012]Cheat
- BZOJ2806(后缀自动机+DP)
- [BZOJ2806]后缀自动机+DP
- BZOJ2806: [Ctsc2012]Cheat
- BZOJ2806-[Ctsc2012]Cheat
- BZOJ2806 [Ctsc2012]Cheat
- 【CTSC2012】bzoj2806 Cheat
- BZOJ 2806 Cheat (后缀自动机+dp)
- 单调队列优化DP
- linux下部署rabbitmq和web项目和jar项目
- volatile
- listview的itemClick监听无响应问题
- post方式传参,在程序中获取不到传的值
- Android的布局技术
- bzoj2806 【Ctsc2012】 Cheat 后缀自动机+单调队列优化dp
- Spring--AOP-环绕通知
- HDOJ 2674 N!Again
- 数据结构----线性表的应用
- PS键盘快捷键大全
- 我与python约个会:30.企业级开发进阶2:网络编程
- POI中设置Excel单元格格式(背景色,居中,字体,边框,列宽,行高,自动换行等)
- 轻松自动化---selenium-webdriver(python) (二)
- java日期工具类DateUtil