BZOJ 4460 [Jsoi2013]广告计划 ——Bitset 后缀自动机

发现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");
}

  

posted @ 2017-07-07 19:46  SfailSth  阅读(252)  评论(0编辑  收藏  举报