Rikka with String

Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has n 01 strings si, and he wants to know the number of 01 antisymmetric strings of length 2L which contain all given strings si as continuous substrings.

A 01 string s is antisymmetric if and only if s[i]≠s[|s|−i+1] for all i∈[1,|s|].

It is too difficult for Rikka. Can you help her?

In the second sample, the strings which satisfy all the restrictions are 000111,001011,011001,100110.

 
Input
The first line contains a number t(1≤t≤5), the number of the testcases.

For each testcase, the first line contains two numbers n,L(1≤n≤6,1≤L≤100).

Then n lines follow, each line contains a 01 string si(1≤|si|≤20).

 
Output
For each testcase, print a single line with a single number -- the answer modulo 998244353.
 
Sample Input
2
2 2
011
001
2 3
011
001
 
Sample Output
1
4
 
 
题解:
  要是能在比赛中A掉就爽了
  和题解做法一样
  

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 1e4+, M = 1e3+,inf = 2e9; const LL mod = 998244353LL; int dp[][][][],sum[][N];
int nex[][N][],cnt0,cnt1,head1,tail1,head0,tail0,q[][N],fail[][N]; void insert(char *s,int p) {
int now = ,len = strlen(s);
for(int i = ; i < len; ++i) {
int index = s[i] - '';
if(!nex[][now][index])
nex[][now][index] = ++cnt0;
sum[][nex[][now][index]] |= sum[][now];
now = nex[][now][index];
//cout<<now<<" "<<index<<endl;
}
sum[][now] |= (<<p); now = ;
for(int i = len-; i >= ; --i) {
int index = s[i] - '';
if(!nex[][now][index])
nex[][now][index] = ++cnt1;
sum[][nex[][now][index]] |= sum[][now];
now = nex[][now][index];
//cout<<now<<" "<<index<<endl;
}
sum[][now] |= (<<p);
} void build_fail() {
head0 = , tail0 = ;head1 = , tail1 = ;
for(int i = ; i < ; ++i)
nex[][][i] = ,nex[][][i] = ; fail[][] = ,fail[][] = ;
q[][tail0++] = ;q[][tail1++] = ;
while(head0 != tail0) {
int now = q[][head0++];
sum[][now] |= sum[][fail[][now]];
for(int i = ; i < ; ++i) {
int p = fail[][now];
if(!nex[][now][i]) {
nex[][now][i] = nex[][p][i];continue;
}
fail[][nex[][now][i]] = nex[][p][i];
q[][tail0++] = nex[][now][i];
}
}
while(head1 != tail1) {
int now = q[][head1++];
sum[][now] |= sum[][fail[][now]];
for(int i = ; i < ; ++i) {
int p = fail[][now];
if(!nex[][now][i]) {
nex[][now][i] = nex[][p][i];continue;
}
fail[][nex[][now][i]] = nex[][p][i];
q[][tail1++] = nex[][now][i];
}
}
}
int len[N],mx,n,L;
char a[N];
int dfs() {
int now = ;
int ret = ;
for(int i = ; i <= *mx; ++i) {
now = nex[][now][len[i]];
ret |= sum[][now];
}
return ret;
}
int ma(int p) {
int now = ;
if(p)
for(int i = mx; i >= ; --i)
now = nex[][now][len[i]];
else
for(int i = mx+; i <= *mx; ++i)
now = nex[][now][len[i]];
return now;
}
void init() {
memset(dp,,sizeof(dp));
memset(nex,,sizeof(nex));
cnt0 = ;mx = -;cnt1 = ;
memset(fail,,sizeof(fail));
memset(sum,,sizeof(sum));
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&L);
init();
for(int i = ; i <= n; ++i) {
scanf("%s",a);
insert(a,i-);
mx = max(mx,(int)strlen(a));
}
int ff = ;
mx-=;
build_fail();
for(int i = ; i < (<<mx); ++i) {
for(int j = ; j <= mx; ++j) len[j] = ((i>>(j-))&);
for(int j = mx+; j <= *mx; ++j) len[j] = ^(len[*mx - j + ]);
int now = dfs();
int z = ma(),f = ma();
dp[ff][z][f][now] += ;
dp[ff][z][f][now] %= mod;
// cout<<i<<" "<<now<<" "<<z<<" "<<f<<endl;
} for(int i = mx; i < L; i++) {
memset(dp[ff^],,sizeof(dp[ff^]));
for(int j = ; j < tail1; ++j) {
for(int k = ; k < tail0; ++k) {
for(int h = ; h < (<<n); ++h) { if(!dp[ff][q[][j]][q[][k]][h]) continue; int p = nex[][q[][j]][],np = nex[][q[][k]][];
int tmp = (h|sum[][p]);
tmp |= sum[][np]; dp[ff^][p][np][tmp] += dp[ff][q[][j]][q[][k]][h];
dp[ff^][p][np][tmp] %= mod; p = nex[][q[][j]][],np = nex[][q[][k]][];
tmp = (h|sum[][p]);
tmp |= sum[][np]; dp[ff^][p][np][tmp] += dp[ff][q[][j]][q[][k]][h];
dp[ff^][p][np][tmp] %= mod; }
}
}
ff^=;
}
LL ans = ;
for(int i = ; i < tail1; ++i)
for(int j = ; j < tail0; ++j)
ans = ( ans + dp[ff][q[][i]][q[][j]][(<<n)-]) % mod;
printf("%lld\n",ans);
}
return ;
}

HDU 6086 Rikka with String AC自动机 + DP的更多相关文章

  1. hdu 6086 -- Rikka with String(AC自动机 + 状压DP)

    题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...

  2. HDU 3341 Lost's revenge AC自动机+dp

    Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)T ...

  3. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

  4. HDU 6086 Rikka with String ——(AC自动机 + DP)

    这是一个AC自动机+dp的问题,在中间的串的处理可以枚举中断点来插入自动机内来实现,具体参见代码. 在这题上不止为何一直MLE,一直找不到结果(lyf相同写法的代码消耗内存较少),还好考虑到这题节点应 ...

  5. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. HDU 6086 Rikka with String

    Rikka with String http://acm.hdu.edu.cn/showproblem.php?pid=6086 题意: 求一个长度为2L的,包含所给定的n的串,并且满足非对称. 分析 ...

  7. HDU 4758 Walk Through Squares(AC自动机+DP)

    题目链接 难得出一个AC自动机,我还没做到这个题呢...这题思路不难想,小小的状压出一维来,不过,D和R,让我wa死了,AC自动机,还得刷啊... #include<iostream> # ...

  8. HDU 2825 Wireless Password【AC自动机+DP】

    给m个单词,由这m个单词组成的一个新单词(两个单词可以重叠包含)长度为n,且新单词中包含的基本单词数目不少于k个.问这样的新单词共有多少个? m很小,用二进制表示新单词中包含基本单词的情况. 用m个单 ...

  9. HDU 4057 Rescue the Rabbit(AC自动机+DP)

    题目链接 一个数组开小了一点点,一直提示wa,郁闷,这题比上个题简单一点. #include <iostream> #include <cstring> #include &l ...

随机推荐

  1. zabbix的安装(一)监控os资源:内存,cpu,io,负载,带宽

    一.Linux下开源监控系统简单介绍1)cacti:存储数据能力强,报警性能差2)nagios:报警性能差,存储数据仅有简单的一段可以判断是否在合理范围内的数据长度,储存在内存中.比如,连续采样数据存 ...

  2. Codeforces Round #345 (Div. 2) E. Table Compression(并查集)

    传送门 首先先从小到大排序,如果没有重复的元素,直接一个一个往上填即可,每一个数就等于当前行和列的最大值 + 1 如果某一行或列上有重复的元素,就用并查集把他们连起来,很(不)显然,处于同一行或列的相 ...

  3. 常州模拟赛d4t3 字符串划分

    题目描述 给你一串由小写字母组成的字符串,希望你把它划分成一些小段,使得每一小段字符串中的字母 都不相同,并且希望分的段数尽量少. 然后,把这些小段按字典序排序后输出,中间由一个空格分隔. 例如:字符 ...

  4. 【leetcode 字符串】466. Count The Repetitions

    https://leetcode.com/problems/count-the-repetitions/description/ 找循环节 https://www.cnblogs.com/grandy ...

  5. Codevs 2801 LOL盖伦的蹲草计划

    题目描述 Description 众所周知,LOL这款伟大的游戏,有个叫盖伦的英雄.他的伟大之处在于他特别喜欢蹲草丛阴人(XL:蹲草阴人也算英雄?!CZQ:没办法,个个都是这么玩的).某日,德玛西亚与 ...

  6. Objective-C单例模式的常用实现

    oc中单例模式可以使用以下方法来实现 + (YourClass *)sharedInstance { static dispatch_once_t once; static YourClass *sh ...

  7. BOJ 2773 第K个与m互质的数

    算法是关键,得出1-m内的互质数,然后类推计算即可.下面有详细说明. #include<iostream> #include<cstring> using namespace ...

  8. android apk程序升级

    1 .设置apk版本号 Androidmanifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/ ...

  9. Peter Norvig:十年学会编程

    为啥都想速成? 随便逛一下书店,你会看到<7天自学Java>等诸如此类的N天甚至N小时学习Visual Basic.Windows.Internet的书.我用亚马逊网站的搜索功能,出版年份 ...

  10. centos6安装概述

    1.1.选择安装类型:[Install or upgrade an existing system]安装或升级现有系统 1.2.介质校验:[Skip]跳过介质校验,校验时间较长 1.3.语言选择:[E ...