zoukankan      html  css  js  c++  java
  • bzoj 3768: spoj 4660 Binary palindrome二进制回文串

    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
    ",ans);
        return 0;
    }
  • 相关阅读:
    HDU 5492 Find a path
    codeforce gym 100548H The Problem to Make You Happy
    Topcoder SRM 144 Lottery
    codeforce 165E Compatible Numbers
    codeforce gym 100307H Hack Protection
    区间DP总结
    UESTC 1321 柱爷的恋爱 (区间DP)
    HDU 4283 You Are the One (区间DP)
    HDU 2476 String painter (区间DP)
    UESTC 426 Food Delivery (区间DP)
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7162635.html
Copyright © 2011-2022 走看看