Rikka with String

http://acm.hdu.edu.cn/showproblem.php?pid=6086

题意:

  求一个长度为2L的,包含所给定的n的串,并且满足非对称。

分析:

  AC自动机+状压dp。

  首先给这个n个串,建立AC自动机。然后去枚举长度为L的一个串,就可以知道另一半了。

  如果给定的串完全存在于左边或者右边,那么直接往AC自动机加入这个串或者取反后的反串。如果是跨越中间,那么暴力的把所有的串,从中间切开,然后判断是否合法,加入到AC自动机上就行,如果长度枚举到了i-1的时候,这些串的状态才有用。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int mod = ;
int ch[][], sta1[], sta2[], fail[], q[], dp[][][];
int Index;
char s[], t[], a[], b[]; void Insert(char *s,int n,int id,bool f) {
int u = ;
for (int i = ; i < n; ++i) {
int c = s[i] - '';
if (!ch[u][c]) ch[u][c] = ++Index;
u = ch[u][c];
}
if (f) sta1[u] |= ( << id);
else sta2[u] |= ( << id);
}
void build() {
int L = , R = ;
for (int i = ; i < ; ++i) if (ch[][i]) q[++R] = ch[][i];
while (L <= R) {
int u = q[L ++];
for (int c = ; c < ; ++c) {
int v = ch[u][c];
if (!v) { ch[u][c] = ch[fail[u]][c]; continue; }
int p = fail[u]; while (p && !ch[p][c]) p = fail[p];
q[++R] = v;
fail[v] = ch[p][c];
sta1[v] |= sta1[fail[v]], sta2[v] |= sta2[fail[v]];
}
}
}
void update(char *s,int n,int id) {
int c1 = , c2 = , f = ;
for (int i = ; i < n - ; ++i) {
c1 = c2 = f = ;
for (int j = i; j >= ; --j) a[c1 ++] = s[j];a[c1] = '\0';
for (int j = i + ; j < n; ++j) b[c2 ++] = s[j]; b[c2] = '\0';
for (int j = ; j < c1 && j < c2; ++j) if (a[j] == b[j]) { f = ; break; }
if (f) continue;
for (int j = c1; j < c2; ++j) a[j] = b[j] == '' ? '' : '';
reverse(a, a + max(c1, c2));
Insert(a, max(c1, c2), id, ); // 长度为max(c1,c2)!!!
}
}
void init() {
memset(dp, , sizeof(dp));
memset(ch, , sizeof(ch));
memset(fail, , sizeof(fail));
memset(sta1, , sizeof(sta1));
memset(sta2, , sizeof(sta2));
}
inline void add(int &x,int y) { x += y; if (x >= mod) x -= mod; }
void solve() {
init();
int n = read(), L = read(), len;
for (int i = ; i < n; ++i) {
scanf("%s", s); len = strlen(s);
Insert(s, len, i, );
for (int j = ; j < len; ++j) t[j] = s[j];
reverse(t, t + len);
for (int j = ; j < len; ++j) t[j] = t[j] == '' ? '' : '';
Insert(t, len, i, );
update(s, len, i);
}
build();
dp[][][] = ;
int All = ( << n) - , now = ;
for (int i = ; i < L; ++i, now ^= )
for (int j = ; j <= Index; ++j)
for (int s = ; s <= All; ++s) {
if (dp[now][j][s] <= ) continue;
for (int c = ; c < ; ++c) {
int nv = ch[j][c], ns = s | sta1[nv];
if (i == L - ) ns |= sta2[nv];
add(dp[now ^ ][nv][ns], dp[now][j][s]);
}
dp[now][j][s] = ;
}
int ans = ;
for (int i = ; i <= Index; ++i) add(ans, dp[now][i][All]);
printf("%d\n",ans % mod);
}
int main() {
for (int T = read(); T --; ) solve();
return ;
}

HDU 6086 Rikka with String的更多相关文章

  1. HDU 6086 Rikka with String AC自动机 + DP

    Rikka with String Problem Description As we know, Rikka is poor at math. Yuta is worrying about this ...

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

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

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

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

  4. hdu.5202.Rikka with string(贪心)

    Rikka with string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  5. HDU 5831 Rikka with Parenthesis II(六花与括号II)

    31 Rikka with Parenthesis II (六花与括号II) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536 ...

  6. HDU 6093 - Rikka with Number | 2017 Multi-University Training Contest 5

    JAVA+大数搞了一遍- - 不是很麻烦- - /* HDU 6093 - Rikka with Number [ 进制转换,康托展开,大数 ] | 2017 Multi-University Tra ...

  7. HDU 5842 Lweb and String(Lweb与字符串)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  8. 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

    // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...

  9. hdu 4850 Wow! Such String! 欧拉回路

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4080264.html 题目链接:hdu 4850 Wow! Such String! 欧拉回 ...

随机推荐

  1. 2456. mode【乱搞】

    Description 给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数. Input 第1行一个正整数n. 第2行n个正整数用空格隔开. Output 一行一个正整数 ...

  2. 劳动节前得空半天-总结一下最近使用的LINUX命令

    一.搜索文件 1.locate xxx.log   全盘搜索xxx.log文件 2.which java       查找命令 3.ll  xxx.log         在目录下查找文件 二.搜索内 ...

  3. [19/04/25-星期四] GOF23_结构型模式(适配器模式、代理模式)

    一.引言 结构模式:核心作用就是从程序的结构上实现松耦合,从而扩大整体的类结构,用来解决更大的问题. 二.适配器模式(adapter) 生活中假设笔记本是标准的USB接口但是外置键盘是圆形接口,这时候 ...

  4. 递归根据父ID 找所有子类ID

    function getinfo($pid){ $str = ''; $row = M('user')->where(array('pid'=>$pid))->select(); i ...

  5. sofar:机器学习检测十题

    http://sofasofa.io/forum_main_post.php?postid=1001084 http://sofasofa.io/forum_main_post.php?postid= ...

  6. 获取 当前显示的 UIViewController

    UIViewController * findBestVC(UIViewController *vc) { if (vc.presentedViewController) { return findB ...

  7. POJ 3080 Blue Jeans 找最长公共子串(暴力模拟+KMP匹配)

    Blue Jeans Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20966   Accepted: 9279 Descr ...

  8. Vue04——vue自定义事件、Router、Vue-cli、发布上线

    一.Vue的自定义事件 点击任何一个按钮,按钮本身计数累加,但是每点击三个按钮中的一个,totalCounter 都要累加. <body> <div id="app&quo ...

  9. 苹果编程语言Swift简介

    Swift是什么? Swift是苹果于WWDC 2014发布的编程语言,The Swift Programming Language的原话: Swift is a new programming la ...

  10. .NET Core中基类可以反射子类的成员

    我们定义一个类DemoA,再定义一个类DemoB继承DemoA.当构造一个DemoB类对象后,我们可以通过其调用基类DemoA中的方法来反射子类DemoB的成员. 新建一个.NET Core控制台项目 ...