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. python,dict的setdefault方法

    @dict的setdefault方法 先看看文档中的解释 setdefault(...)    D.setdefault(k[,d]) -> D.get(k,d), also set D[k]= ...

  2. Dubbo特性

    dubbo.properties Dubbo 将自动加载 classpath 根目录下的dubbo.properties,可以通过JVM启动参数 -Ddubbo.properties.file=xxx ...

  3. Kali-linux使用社会工程学工具包(SET)

    社会工程学工具包(SET)是一个开源的.Python驱动的社会工程学渗透测试工具.这套工具包由David Kenned设计,而且已经成为业界部署实施社会工程学攻击的标准.SET利用人们的好奇心.信任. ...

  4. [转载] Python协程从零开始到放弃

    Python协程从零开始到放弃 Web安全 作者:美丽联合安全MLSRC   2017-10-09  3,973   Author: lightless@Meili-inc Date: 2017100 ...

  5. BigDecimal.setScale用法总结

    1. BigDecimal num1 = new BigDecimal(2.225667);//这种写法不允许,会造成精度损失 2. BigDecimal num2 = new BigDecimal( ...

  6. [LuoguP1363]幻想迷宫

    [LuoguP1363]幻想迷宫(Link) 现在有一个迷宫,从迷宫边界的任意一点可以走到对面,即:若都是路面,则可以从\((1, i)\)走到\((N, i)\).其余情况依旧.问是否可以从指定的起 ...

  7. HDU1005 Number Sequence(找规律,周期是变化的)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1005 Number Sequence Time Limit: 2000/1000 MS (Java/O ...

  8. Oracle输出数字1-10

    ,) from dual connect by level<

  9. first-child伪类选择器

    原文链接地址:https://www.cnblogs.com/wangmeijian/p/4562304.html :first-child 选择器用于选取属于其父元素的首个子元素的指定选择器.——w ...

  10. 单片机采集的MPU6050原始数据对应关系

    转自:https://blog.csdn.net/u013636775/article/details/69668860 单片机采集的MPU6050原始数据对应关系 1.陀螺仪 如下图, 陀螺仪的范围 ...