bzoj 4460 : [Jsoi2013]广告计划
2016-05-26 18:11
232 查看
脑残一下午
首先,对于所有字符串建立后缀自动机
这里可以是广义后缀自动机或者狭义后缀自动机,我会给出2份代码
然后是匹配时间
我们枚举答案,问题变成一个答案是否能够被成功匹配
观察发现,如果当前答案为ans,那么1,1+ans,1+ans∗2......都会在一排一起出现
同理 2,2+ans,2+ans∗2......也会这样
我们定义have[i][j]表示i,i+ans,i+ans∗2......是否在第j列出现
这个可以在后缀自动机上求right集合实现
那么ans什么情况会成为答案呢?
我们观察样例,have[1][2],have[2][3],have[3][3]同时存在的时候,ans为答案
结论:ans为答案,仅当存在一个x,使得have[1][x],have[2][x],have[3][x]....have[ans][x]同时存在,但是存在例外:x有一次机会在中间某个地方+1
然后暴力跑就好了,由于我复杂度没有卡满所以跑得飞快QAQ
顺便说一句,两份代码统计right的方法是一样的,可以互换,但是有基数排序的方法
代码
狭义后缀自动机
广义后缀自动机
首先,对于所有字符串建立后缀自动机
这里可以是广义后缀自动机或者狭义后缀自动机,我会给出2份代码
然后是匹配时间
我们枚举答案,问题变成一个答案是否能够被成功匹配
观察发现,如果当前答案为ans,那么1,1+ans,1+ans∗2......都会在一排一起出现
同理 2,2+ans,2+ans∗2......也会这样
我们定义have[i][j]表示i,i+ans,i+ans∗2......是否在第j列出现
这个可以在后缀自动机上求right集合实现
那么ans什么情况会成为答案呢?
我们观察样例,have[1][2],have[2][3],have[3][3]同时存在的时候,ans为答案
结论:ans为答案,仅当存在一个x,使得have[1][x],have[2][x],have[3][x]....have[ans][x]同时存在,但是存在例外:x有一次机会在中间某个地方+1
然后暴力跑就好了,由于我复杂度没有卡满所以跑得飞快QAQ
顺便说一句,两份代码统计right的方法是一样的,可以互换,但是有基数排序的方法
代码
狭义后缀自动机
#include<bits/stdc++.h> #define N 20005 using namespace std; namespace sam{ int last=1,tot=1; int t [27],pre ,val ,deep ; bitset<102>right ; 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 ; 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 20005 using namespace std; namespace sam{ int last=1,tot=1; int t [27],pre ,val ,deep ; bitset<102>right ; 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 ,fir ,to ,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); } } }
相关文章推荐
- UVa 10394-Twin Primes
- POJ1979 Red and Black 题解
- HDOJ 1001 递归方法
- AcceptCM Contest - 1 题解
- HDU 1203 I NEED A OFFER! 题解
- UVA 401 Palindromes 题解
- UVA 10010 - Where's Waldorf? 题解
- 【题解】洛谷1164小A点菜
- 杭电试题分类题解
- hdoj1017--A Mathematical Curiosity
- hdoj1020--Encoding
- hdoj1002--A + B Problem II
- Codeforces 625D Finals in arithmetic(Codeforces Round #342 (Div. 2) D) 题解
- Codeforces 625E Frog Fights (Codeforces Round #342 (Div. 2) E) 题解
- CF582A GCD Table
- HDU2068 RPG的错排
- HDU2191悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
- HDU2046骨牌铺方格
- poj2312题解
- 【bzoj1033】杀蚂蚁