BZOJ 4460 [Jsoi2013]广告计划 ——Bitset 后缀自动机
Posted SfailSth ——Salt Fish
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4460 [Jsoi2013]广告计划 ——Bitset 后缀自动机相关的知识,希望对你有一定的参考价值。
Orz,好久没有自己想出正解来了。
看了看题目并不是很会做,然后看了一下题解,
这都是些什么玩意。
没看懂只能回来自己想。
然后发现n比较小,直接枚举答案,然后发现连续的一段是确定的,然后我们只需要判断每个位置是否有这个连续的一段就好了
发现起点不同,最后的位置可能会有差距,所以DP一下就好了
然后用0表示未折返,1表示从最下面换到最上面,然后就是发现所有位置互不干扰,直接用Bitset压一下就可以做了
复杂度N^3/64
#include <bits/stdc++.h> using namespace std; #define maxn 100005 int fa[maxn],go[maxn][26],last,cnt,l[maxn],v[maxn],q[maxn]; char s[maxn]; bitset <205> bit[maxn],Nothing,dp[2][2]; void init() { last=cnt=1; } void add(int x,int pos) { int p=last,q; if ((q=go[p][x])){ if (l[q]==l[p]+1) last=q; else{ int nq=++cnt; l[nq]=l[p]+1; memcpy(go[nq],go[q],sizeof go[q]); fa[nq]=fa[q]; fa[q]=nq; for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq; last=nq; } } else{ int np=++cnt; l[np]=l[p]+1; for (;p&&!go[p][x];p=fa[p]) go[p][x]=np; if (!p) fa[np]=1; else{ q=go[p][x]; if (l[q]==l[p]+1) fa[np]=q; else { int nq=++cnt; l[nq]=l[p]+1; memcpy(go[nq],go[q],sizeof go[q]); fa[nq]=fa[q]; fa[q]=fa[np]=nq; for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq; } } last=np; } bit[last][pos]=1; } void insert() { last=1; scanf("%s",s+1); int Len=strlen(s+1); for (int i=1;i<=Len;++i){ add(s[i]-‘a‘,i); } } void Radix() { for (int i=1;i<=cnt;++i) v[l[i]]++; for (int i=1;i<=cnt;++i) v[i]+=v[i-1]; for (int i=cnt;i>=1;--i) q[v[l[i]]--]=i; for (int i=cnt;i>=1;--i) bit[fa[q[i]]]|=bit[q[i]]; } int n,m,Len; char t[maxn]; bool test(int x) { int now=1,pre=0; dp[now][0].reset(); dp[now][1].reset(); dp[now][0].set(); int all=(Len+x-1)/x; for (int i=1;i<=x;++i){ int pos=1,flag=1,tmp=0; now^=1; pre^=1; for (int j=i;j<=Len;j+=x){ pos=go[pos][t[j]-‘a‘]; tmp++; if (!pos) {flag=0;break;} } if (flag){ bitset<205> Match=bit[pos]; if (tmp<all) Match<<=1; dp[now][0]=dp[pre][0]&Match; dp[now][1]=dp[pre][1]&Match; dp[now][1]=(dp[pre][1]|(dp[pre][0]<<1))&Match; } else{ return false; } } if (dp[now][0].count()||dp[now][1].count()) return true; else return false; } int main() { #ifdef WXL freopen("in.txt","r",stdin); #endif init(); scanf("%d%d",&n,&m); for (int i=1;i<=n;++i){ insert(); } bitset<205> Test; Radix(); Nothing.reset(); scanf("%s",t+1); Len=strlen(t+1); for (int i=1;i<=Len;++i){ if (test(i)) { printf("%d\n",i); return 0; } } printf("No Sulotion\n"); }
以上是关于BZOJ 4460 [Jsoi2013]广告计划 ——Bitset 后缀自动机的主要内容,如果未能解决你的问题,请参考以下文章
bzoj千题计划120:bzoj1032[JSOI2007]祖码Zuma
bzoj千题计划119:bzoj1029: [JSOI2007]建筑抢修
bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix
bzoj千题计划123:bzoj1027: [JSOI2007]合金