bzoj 4460 : [Jsoi2013]广告计划
来源:互联网 发布:c语言为什么要加入指针 编辑:程序博客网 时间:2024/05/22 10:31
脑残一下午
首先,对于所有字符串建立后缀自动机
这里可以是广义后缀自动机或者狭义后缀自动机,我会给出2份代码
然后是匹配时间
我们枚举答案,问题变成一个答案是否能够被成功匹配
观察发现,如果当前答案为
同理
我们定义
这个可以在后缀自动机上求
那么ans什么情况会成为答案呢?
我们观察样例,
结论:
然后暴力跑就好了,由于我复杂度没有卡满所以跑得飞快QAQ
顺便说一句,两份代码统计
代码
狭义后缀自动机
#include<bits/stdc++.h>#define N 20005using namespace std;namespace sam{ int last=1,tot=1; int t[N][27],pre[N],val[N],deep[N]; bitset<102>right[N]; void insert(int x,int ps){ int np=++tot,now=last;last=np;val[tot]=1; deep[np]=deep[now]+1;right[np][ps]=1; while(now&&!t[now][x]){ t[now][x]=np;now=pre[now]; } if(!now)pre[np]=1; else{ int q=t[now][x],p=now; if(deep[p]+1==deep[q])pre[np]=q; else{ int nq=++tot;deep[nq]=deep[p]+1; pre[nq]=pre[q];pre[np]=pre[q]=nq; memcpy(t[nq],t[q],sizeof t[q]);right[nq]=right[q]; while(now&&t[now][x]==q)t[now][x]=nq,now=pre[now]; } } } struct node{ int id,x; friend bool operator < (const node &a,const node &b){ return a.x<b.x; } }s[N]; void add(){ for(int i=1;i<=tot;i++)s[i]=(node){i,deep[i]}; sort(s+1,s+tot+1); for(int i=tot;i>=2;i--){ right[pre[s[i].id]]|=right[s[i].id]; } }}char p[205];int n,m,len;bitset<102>have[205];int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%s",p+1); for(int j=1;j<=m;j++){ sam::insert(p[j]-'a',j); } sam::insert(26,0); } sam::add(); scanf("%s",p+1);len=strlen(p+1); for(int ans=1;ans<=len;ans++){ for(int j=1;j<=ans;j++){ int x=1,y=j,f=0; while(y<=len){ x=sam::t[x][p[y]-'a']; y=y+ans;f++; } have[j]=sam::right[x]>>(f-1); } for(int i=1;i<=m;i++){ if(!have[1][i])continue; int a=1,b=1; for(int j=2;j<=ans;j++){ b=(a|b)&&have[j][i+1]; a&=have[j][i]; if((!a)&&(!b))break; } if(a|b)cout<<ans<<endl,exit(0); } }}
广义后缀自动机
#include<bits/stdc++.h>#define N 20005using namespace std;namespace sam{ int last=1,tot=1; int t[N][27],pre[N],val[N],deep[N]; bitset<102>right[N]; void insert(int x,int ps){ if(t[last][x]){ last=t[last][x];right[x][ps]=1;return; } int np=++tot,now=last;last=np;val[tot]=1; deep[np]=deep[now]+1;right[np][ps]=1; while(now&&!t[now][x]){ t[now][x]=np;now=pre[now]; } if(!now)pre[np]=1; else{ int q=t[now][x],p=now; if(deep[p]+1==deep[q])pre[np]=q; else{ int nq=++tot;deep[nq]=deep[p]+1; pre[nq]=pre[q];pre[np]=pre[q]=nq; memcpy(t[nq],t[q],sizeof t[q]);right[nq]=right[q]; while(now&&t[now][x]==q)t[now][x]=nq,now=pre[now]; } } } int nxt[N],fir[N],to[N],Sz; void add(int x,int y){ nxt[++Sz]=fir[x];fir[x]=Sz;to[Sz]=y; } void dfs(int x){ for(int u=fir[x];u;u=nxt[u]){ dfs(to[u]);right[x]|=right[to[u]]; } } void add(){ for(int i=2;i<=tot;i++)add(pre[i],i); dfs(1); }}char p[205];int n,m,len;bitset<102>have[205];int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%s",p+1); for(int j=1;j<=m;j++){ sam::insert(p[j]-'a',j); } sam::last=1; } sam::add(); scanf("%s",p+1);len=strlen(p+1); for(int ans=1;ans<=len;ans++){ for(int j=1;j<=ans;j++){ int x=1,y=j,f=0; while(y<=len){ x=sam::t[x][p[y]-'a']; y=y+ans;f++; } have[j]=sam::right[x]>>(f-1); } for(int i=1;i<=m;i++){ if(!have[1][i])continue; int a=1,b=1; for(int j=2;j<=ans;j++){ b=(a|b)&&have[j][i+1]; a&=have[j][i]; if((!a)&&(!b))break; } if(a|b)cout<<ans<<endl,exit(0); } }}
0 0
- bzoj 4460 : [Jsoi2013]广告计划
- BZOJ 4459: [Jsoi2013]丢番图
- bzoj 4459: [Jsoi2013]丢番图 数学
- [数学] BZOJ 4459 [Jsoi2013]丢番图
- bzoj 4466 : [Jsoi2013]超立方体
- bzoj 4461: [Jsoi2013]美丽家园
- bzoj 4479: [Jsoi2013]吃货jyy
- bzoj 4464 [Jsoi2013]旅行时的困惑
- BZOJ 4466 [Jsoi2013]超立方体【模拟
- bzoj 4480: [Jsoi2013]快乐的jyy
- bzoj 4465: [Jsoi2013]游戏中的学问
- 广告计划
- JSOI2013 密码
- 【BZOJ 2132】 圈地计划
- bzoj 2132: 圈地计划
- [BZOJ 1758]重建计划
- bzoj 2132: 圈地计划
- BZOJ 3333: 排队计划
- synchronized详解
- iOS HTTP接口授权
- java50中经典算法
- vb登陆界面设计
- iOS客户端、java服务器的通信用RSA加密
- bzoj 4460 : [Jsoi2013]广告计划
- android 中SD卡访问权限问题【转自Eagle的博客】
- 1000以内任意10个整数之和
- Xcode编译出现的二进制错误(xxname.o)
- ubuntu 正在读取软件包列表... 有错误!
- iOS图书动画
- CUDA之矩阵乘法——非方阵计算
- 程序是怎样跑起来的-第09章 操作系统和应用的关系
- 5.26 vb作业