码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 3768: spoj 4660 Binary palindrome二进制回文串

时间:2017-07-13 21:56:18      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:void   sizeof   bsp   lin   lap   超过   code   uil   std   

Description

给定k个长度不超过L的01串,求有多少长度为n的01串S满足:

1.该串是回文串

2.该串不存在两个不重叠的子串,在给定的k个串中。

即不存在a<=b<c<=d,S[a,b]是k个串中的一个,S[c,d]是k个串中的一个

(It does not contain two non-overlapped substrings in the given list of K binary strings.)

举个例子,若给定2(k=2)个01串:101和1001

1010001和1010101均不满足条件。前者不满足条件1,后者不满足条件2

Input

第一行两个整数n,k

以下k行,每行一个01串

Output

输出一个整数表示答案,答案mod 1000000007(10^9+7)
对原串和反串分别建ac自动机,从两边向中间处理回文串,同时在自动机上走,若匹配到一个串就记录并回到起点
dp状态表示为 当前已确定前缀、后缀在ac自动机上的位置,以及是否已匹配到一个串 的方案数
最后检查是否在跨过中点的位置匹配到一个串
#include<cstdio>
#include<cstring>
#include<algorithm>
const int P=1e9+7;
int n,k,ls[33];
char s[33][33];
inline void inc(int&a,int b){
    b+=a-P;
    a=b+(b>>31&P);
}
struct acam{
    int ch[907][2],fa[907];
    int S[907][33];
    bool e[907];
    int ptr;
    acam(){
        memset(this,0,sizeof(acam));
        ptr=1;
        ch[0][0]=ch[0][1]=1;
    }
    void ins(char*s,int a){
        int w=1;
        for(int i=0;s[i];++i){
            int c=s[i]-0,&u=ch[w][c];
            if(!u)u=++ptr;
            w=u;
            S[w][a]|=1<<i;
        }
        e[w]=1;
    }
    void ins(char*s,int a,int len){
        int w=1;
        for(int i=len-1;i>=0;--i){
            int c=s[i]-0,&u=ch[w][c];
            if(!u)u=++ptr;
            w=u;
            S[w][a]|=1<<i;
        }
        e[w]=1;
    }
    void build(){
        int q[907],ql=0,qr=0;
        q[++qr]=1;
        while(ql!=qr){
            int w=q[++ql];
            for(int i=0;i<2;++i){
                int&u=ch[w][i];
                (u?fa[q[++qr]=u]:u)=ch[fa[w]][i];
            }
        }
        for(int i=2;i<=qr;++i){
            int w=q[i],f=fa[w];
            e[w]|=e[f];
            for(int j=0;j<k;++j)S[w][j]|=S[f][j];
        }
    }
}t1,t2;
int f[2][907][907][2];
int main(){
    scanf("%d%d",&n,&k);
    for(int i=0;i<k;++i){
        scanf("%s",s[i]);
        ls[i]=strlen(s[i]);
        t1.ins(s[i],i);
        t2.ins(s[i],i,ls[i]);
    }
    t1.build();
    t2.build();
    int now=0;
    f[0][1][1][0]=1;
    for(int t=0;t<n/2;++t,now^=1){
        memset(f[now^1],0,sizeof(f[0][0])*(t1.ptr+2));
        for(int c=0;c<2;++c){
            for(int a=1;a<=t1.ptr;++a)if(!t1.e[a]){
                int a1=t1.ch[a][c],is=0;
                if(t1.e[a1])a1=1,is=1;
                int(*f1a)[2]=f[now^1][a1];
                int(*f0a)[2]=f[now][a];
                for(int b=1;b<=t2.ptr;++b)if(!t2.e[b]){
                    int b1=t2.ch[b][c];
                    int v=is;
                    if(t2.e[b1])b1=1,++v;
                    for(int x=0;x+v<2;++x){
                        inc(f1a[b1][x+v],f0a[b][x]);
                    }
                }
            }
        }
    }
    if(n&1){
        memset(f[now^1],0,sizeof(f[0][0])*(t1.ptr+2));
        for(int c=0;c<2;++c){
            for(int a=1;a<=t1.ptr;++a)if(!t1.e[a]){
                int a1=t1.ch[a][c],is=0;
                if(t1.e[a1])a1=1,is=1;
                int(*f1a)[2]=f[now^1][a1];
                int(*f0a)[2]=f[now][a];
                for(int b=1;b<=t2.ptr;++b)if(!t2.e[b]){
                    int v=is;
                    for(int x=0;x+v<2;++x){
                        inc(f1a[b][x+v],f0a[b][x]);
                    }
                }
            }
        }
        now^=1;
    }
    int ans=0;
    for(int a=1;a<=t1.ptr;++a){
        for(int b=1;b<=t2.ptr;++b){
            inc(ans,f[now][a][b][0]);
            for(int c=0;c<k;++c)if(t1.S[a][c]<<1&t2.S[b][c])goto o;
            inc(ans,f[now][a][b][1]);
            o:;
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

bzoj 3768: spoj 4660 Binary palindrome二进制回文串

标签:void   sizeof   bsp   lin   lap   超过   code   uil   std   

原文地址:http://www.cnblogs.com/ccz181078/p/7162635.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!