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+;
int n,k,ls[];
char s[][];
inline void inc(int&a,int b){
b+=a-P;
a=b+(b>>&P);
}
struct acam{
int ch[][],fa[];
int S[][];
bool e[];
int ptr;
acam(){
memset(this,,sizeof(acam));
ptr=;
ch[][]=ch[][]=;
}
void ins(char*s,int a){
int w=;
for(int i=;s[i];++i){
int c=s[i]-'',&u=ch[w][c];
if(!u)u=++ptr;
w=u;
S[w][a]|=<<i;
}
e[w]=;
}
void ins(char*s,int a,int len){
int w=;
for(int i=len-;i>=;--i){
int c=s[i]-'',&u=ch[w][c];
if(!u)u=++ptr;
w=u;
S[w][a]|=<<i;
}
e[w]=;
}
void build(){
int q[],ql=,qr=;
q[++qr]=;
while(ql!=qr){
int w=q[++ql];
for(int i=;i<;++i){
int&u=ch[w][i];
(u?fa[q[++qr]=u]:u)=ch[fa[w]][i];
}
}
for(int i=;i<=qr;++i){
int w=q[i],f=fa[w];
e[w]|=e[f];
for(int j=;j<k;++j)S[w][j]|=S[f][j];
}
}
}t1,t2;
int f[][][][];
int main(){
scanf("%d%d",&n,&k);
for(int i=;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=;
f[][][][]=;
for(int t=;t<n/;++t,now^=){
memset(f[now^],,sizeof(f[][])*(t1.ptr+));
for(int c=;c<;++c){
for(int a=;a<=t1.ptr;++a)if(!t1.e[a]){
int a1=t1.ch[a][c],is=;
if(t1.e[a1])a1=,is=;
int(*f1a)[]=f[now^][a1];
int(*f0a)[]=f[now][a];
for(int b=;b<=t2.ptr;++b)if(!t2.e[b]){
int b1=t2.ch[b][c];
int v=is;
if(t2.e[b1])b1=,++v;
for(int x=;x+v<;++x){
inc(f1a[b1][x+v],f0a[b][x]);
}
}
}
}
}
if(n&){
memset(f[now^],,sizeof(f[][])*(t1.ptr+));
for(int c=;c<;++c){
for(int a=;a<=t1.ptr;++a)if(!t1.e[a]){
int a1=t1.ch[a][c],is=;
if(t1.e[a1])a1=,is=;
int(*f1a)[]=f[now^][a1];
int(*f0a)[]=f[now][a];
for(int b=;b<=t2.ptr;++b)if(!t2.e[b]){
int v=is;
for(int x=;x+v<;++x){
inc(f1a[b][x+v],f0a[b][x]);
}
}
}
}
now^=;
}
int ans=;
for(int a=;a<=t1.ptr;++a){
for(int b=;b<=t2.ptr;++b){
inc(ans,f[now][a][b][]);
for(int c=;c<k;++c)if(t1.S[a][c]<<&t2.S[b][c])goto o;
inc(ans,f[now][a][b][]);
o:;
}
}
printf("%d\n",ans);
return ;
}

bzoj 3768: spoj 4660 Binary palindrome二进制回文串的更多相关文章

  1. [LeetCode] Shortest Palindrome 最短回文串

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  2. lintcode :Valid Palindrome 有效回文串

    题目: 有效回文串 给定一个字符串,判断其是否为一个回文串.只包含字母和数字,忽略大小写. 样例 "A man, a plan, a canal: Panama" 是一个回文. & ...

  3. BZOJ.2565.[国家集训队]最长双回文串(Manacher/回文树)

    BZOJ 洛谷 求给定串的最长双回文串. \(n\leq10^5\). Manacher: 记\(R_i\)表示以\(i\)位置为结尾的最长回文串长度,\(L_i\)表示以\(i\)开头的最长回文串长 ...

  4. [leetcode]125. Valid Palindrome判断回文串

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...

  5. [LeetCode] 214. Shortest Palindrome 最短回文串

    Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  6. poj 3280 Cheapest Palindrome ---(DP 回文串)

    题目链接:http://poj.org/problem?id=3280 思路: dp[i][j] :=第i个字符到第j个字符之间形成回文串的最小费用. dp[i][j]=min(dp[i+1][j]+ ...

  7. poj3280 Cheapest Palindrome(回文串区间dp)

    https://vjudge.net/problem/POJ-3280 猛刷简单dp第一天第三题. 这个据说是[求字符串通过增减操作变成回文串的最小改动次数]的变体. 首先增减操作的实质是一样的,所以 ...

  8. Atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning 回文串划分

    题目链接 题意 给定一个字符串(长度\(\leq 2e5\)),将其划分成尽量少的段,使得每段内重新排列后可以成为一个回文串. 题解 分析 每段内重新排列后是一个回文串\(\rightarrow\)该 ...

  9. 214 Shortest Palindrome 最短回文串

    给一个字符串 S, 你可以通过在字符串前面添加字符将其转换为回文串.找到并返回可以用这种方式转换的最短回文串.例如:给出 "aacecaaa",返回 "aaacecaaa ...

随机推荐

  1. 获取URL中的链接(可中文也可英文)

    //既能获取中文url也能英文function getUrlParam(key) { // 获取参数 var url = window.location.search; // 正则筛选地址栏 var ...

  2. linux fdisk 添加硬盘,分区,挂载,永久挂载

    具体步骤: 1.SSH登陆服务器: 2.列出所有硬盘: 命令:ll /dev/disk/by-path 我这里还有个sda 3.查看磁盘分区情况: 命令 :fdisk -l 最上面两部分表示我有两个物 ...

  3. 卡巴斯基KAV2013 – 免费一年 (六一活动)

    赠送时间:2013年5月31日10时 至 2013年6月1日24时赠送产品:卡巴斯基反病毒软件2013(一年版)赠送方式:产品激活码将以电邮方式发送到您提交信息的邮箱里,每个邮箱仅能领取一个激活码.温 ...

  4. Java数字签名算法--RSA

    签名具有的特性: 安全性 抗否认性 数字签名:带有密钥(公钥.私钥)的消息摘要算法(使用私钥进行签名,使用公钥进行验证) 数字签名算法:RSA.DSA.ECDSA 数字签名特性: 验证数据完整性 认证 ...

  5. ElasticSearch—分页查询

    ElasticSearch查询—分页查询详解 Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回.那么,如何实现分页查询呢? 按照一般的查询流程来说,如 ...

  6. 结构体:HASH表模板

    这种 HASHMAP 就是一个链式前向星的表: 其中: init 函数:hashmap 创建初始化: check 函数:寻找 hash 表中是否有需要查找的值,若有则返回 1 ,否则返回 0 :遍历方 ...

  7. synchronized (lock) 买票demo 线程安全

    加锁防止多个线程执行同一段代码! /** http://blog.51cto.com/wyait/1916898 * @author * @since 11/10/2018 * 某电影院目前正在上映贺 ...

  8. [LOJ6029~6052]雅礼集训 2017 选做

    Link 代码可以在loj上看我的提交记录. Day 1 [LOJ6029]市场 对于一次除法操作,若区间内所有数的减少量均相同则可视作区间减法,否则暴力递归下去.显然一个线段树节点只会被暴力递归进去 ...

  9. 树莓派挂载和卸载U盘或移动硬盘

    通常我们在 /mnt 或 /media 目录下新建一个目录udisk作为挂载点 sudo mkdir /mnt/udisk 1.手动挂载: 挂载命令: sudo mount -o uid=pi,gid ...

  10. 详解SID之终结篇

    今天测试某款监控软件时遇到一个比较棘手的问题,这款软件需要在被监控端安装客户端程序.成功在第一个节点安装好客户端后问题出现了,在其他节点安装时报错无法安装.软件报的错误信息无从下手且系统日志也看不出什 ...