D. Tavas and Malekas DFS模拟 + kmp + hash || kmp + hash
http://codeforces.com/contest/535/problem/D
如果真的要把m个串覆盖上一个串上面,是可以得,不会超时。
要注意到一点,全部覆盖后再判断时候合法,和边放边判断,结果是一样的,后者还更难做到。
那么就是先按顺序把串覆盖上去,已经存在的就不去覆盖了,然后kmp一次记录匹配位置,判断即可。
用DFS覆盖,DFS回溯的时候记录一个数组tonext[i]表示第i个点的第一个空位是tonext[i],这样覆盖上去就是O(n)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e6 + ;
const int MOD = 1e9 + ;
int tonext[maxn];
int ret;
char str[maxn];
char sub[maxn];
void dfs(int cur, int k, int from) {
if (k < ) return;
if (k == ) {
ret = cur;
return;
}
if (tonext[cur] != cur) {
ret = tonext[cur];
dfs(tonext[cur], k - (tonext[cur] - cur), from + tonext[cur] - cur);
tonext[cur] = ret;
} else {
ret = cur + ;
str[cur] = sub[from];
dfs(cur + , k - , from + );
tonext[cur] = ret;
}
}
int a[maxn];
bool HASH[maxn];
int kmpnext[maxn];
void get_next(char sub[], int lensub) {
int i = , j = ;
kmpnext[] = ;
while (i <= lensub) {
if (j == || sub[i] == sub[j]) {
kmpnext[++i] = ++j;
} else j = kmpnext[j];
}
return;
}
void kmp(int lenstr, int lensub) {
int i = , j = ;
while (i <= lenstr) {
if (j == || str[i] == sub[j]) {
++i;
++j;
} else j = kmpnext[j];
if (j == lensub + ) {
HASH[i - lensub] = true;
j = kmpnext[j];
}
}
return;
}
void work() {
int lenstr, m;
scanf("%d%d", &lenstr, &m);
for (int i = ; i <= lenstr; ++i) {
tonext[i] = i;
str[i] = 'A';
// printf("f");
}
// printf("%c\n", str[1]);
scanf("%s", sub + );
int lensub = strlen(sub + );
for (int i = ; i <= m; ++i) {
scanf("%d", &a[i]);
dfs(a[i], lensub, );
}
str[lenstr + ] = '\0';
// printf("%s\n", str + 1);
get_next(sub, lensub);
kmp(lenstr, lensub);
for (int i = ; i <= m; ++i) {
if (!HASH[a[i]]) {
cout << << endl;
return;
}
}
LL ans = ;
for (int i = ; i <= lenstr; ++i) {
if (str[i] == 'A') {
ans *= ;
if (ans >= MOD) ans %= MOD;
}
}
cout << ans << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}
开始的时候想不到直接kmp
用的其实就是kmp的next数组,不断next[next[]]
就是记录所有的前缀和后缀相等。
对于abc****abc,也就是前后缀相等的话,长度是3
记上一个覆盖到的位置是pos[i - 1] + lensub - 1
然后如果这个和他没交集,就算,如果有,要判断。怎么判断呢?
算出交集大小,如果交集刚好是3,那么是可以得。否则,是NO
交集是3说明后缀的那3个和前缀匹配了。
注意m可能是0
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e6 + ;
const int MOD = 1e9 + ;
char sub[maxn];
int tonext[maxn];
int pos[maxn];
bool book[maxn];
void get_next(char sub[], int lensub) {
int i = , j = ;
tonext[] = ;
while (i <= lensub) {
if (j == || sub[i] == sub[j]) {
tonext[++i] = ++j;
} else j = tonext[j];
}
return;
}
void work() {
int lenstr, m;
// cin >> lenstr >> m;
// cin >> sub + 1;
scanf("%d%d", &lenstr, &m);
scanf("%s", sub + );
int lensub = strlen(sub + );
get_next(sub, lensub);
for (int i = ; i <= m; ++i) {
// cin >> pos[i];
scanf("%d", &pos[i]);
}
int t = tonext[lensub + ];
while (t != ) {
book[t - ] = true;
t = tonext[t];
}
int total = lenstr - lensub;
if (m == ) {
total += lensub;
}
for (int i = ; i <= m; ++i) {
int to = pos[i - ] + lensub - ;
int haha = to - pos[i] + ;
if (haha <= ) {
total -= lensub;
continue;
}
if (!book[haha]) {
printf("0\n");
return;
}
total -= lensub - haha;
}
LL ans = ;
for (int i = ; i <= total; ++i) {
ans *= ;
if (ans >= MOD) ans %= MOD;
}
printf("%I64d\n", ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}
D. Tavas and Malekas DFS模拟 + kmp + hash || kmp + hash的更多相关文章
- Codeforces Round #299 (Div. 2) D. Tavas and Malekas kmp
题目链接: http://codeforces.com/problemset/problem/535/D D. Tavas and Malekas time limit per test2 secon ...
- D. Tavas and Malekas 解析(字串匹配)
Codeforce 535 D. Tavas and Malekas 解析(字串匹配) 今天我們來看看CF535D 題目連結 題目 給你一個字串$p$和一些$index$代表字串$p$在哪些位置會和長 ...
- Codeforces 535D - Tavas and Malekas
535D - Tavas and Malekas 题目大意:给你一个模板串,给你一个 s 串的长度,告诉你 s 串中有 m 个模板串并告诉你,他们的其实位置, 问你这样的 s 串总数的多少,答案对1e ...
- Vijos P1114 FBI树【DFS模拟,二叉树入门】
描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串. FBI树是一种二叉树1,它的结点类型也包括F结点,B结点和I结点三种 ...
- 矩阵hash + KMP - UVA 12886 The Big Painting
The Big Painting Problem's Link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=88791 M ...
- HDU 5438 Ponds dfs模拟
2015 ACM/ICPC Asia Regional Changchun Online 题意:n个池塘,删掉度数小于2的池塘,输出池塘数为奇数的连通块的池塘容量之和. 思路:两个dfs模拟就行了 # ...
- 字符串Hash/树Hash学习笔记
哈希 Tags:字符串 作业部落 评论地址 一.概述 百度百科: 散列表(Hash table/哈希表),是根据关键码值(Key value)而直接进行访问的数据结构. 哈希表常用于比较两个字符串是否 ...
- Hash Map (Hash Table)
Reference: Wiki PrincetonAlgorithm What is Hash Table Hash table (hash map) is a data structure use ...
- kmp&扩展kmp
kmp: KMP的主要目的是求B是不是A的子串,以及若是,B在A中所有出现的位置 写的很详细的大佬的博客:http://www.matrix67.com/blog/archives/115 模板: / ...
随机推荐
- curl: (7) Failed to connect to 127.0.0.1 port 1086: Connection refused
今天我用curl命令,无论如何都是出现: curl: (7) Failed to connect to 127.0.0.1 port 1086: Connection refused 找了很久,不知道 ...
- chmod|chown|chgrp和用法和区别
1.chgrp(改变文件所属用户组) chgrp 用户组 文件名 ###就是这个格了.如果整个目录下的都改,则加-R参数用于递归. 如:chgrp -R user smb.conf 2.c ...
- BZOJ2163: 复杂的大门
BZOJ2163: 复杂的大门 Description 你去找某bm玩,到了门口才发现要打开他家的大门不是一件容易的事……他家的大门外有n个站台,用1到n的正整数编号.你需要对每个站台访问一定次数以后 ...
- Ural 1635 Mnemonics and Palindromes(DP)
题目地址:space=1&num=1635">Ural 1635 又是输出路径的DP...连着做了好多个了. . 状态转移还是挺简单的.要先预处理出来全部的回文串,tag[i] ...
- uCos临界区保护
定义有三种method,stm32f4采用的是第三种:将当前中断的状态标志保存在一个局部变量cpu_sr中,然后再关闭中断.cpu_sr是一个局部变量,存在于所有需要关中断的函数中.注意到,在使用了该 ...
- html5--6-55 动画效果-关键帧动画
html5--6-55 动画效果-关键帧动画 实例 @charset="UTF-8"; div{ width: 150px; height: 150px; font-size: 2 ...
- erlang的base64解码问题
在收到客户端的数字签名signature后,需要对signature做base64的解码.代码如下所示: validate(SignedRequest) -> RequestParts = st ...
- 每次rand出来都是41?说好的随机数呢?!
rand()函数是C++标准函数库提供的随机数生成器,生成0-RAND_MAX之间的一个"伪随机"整数,理论上可以产生的最大数值为2^16-1,即32767. rand()函数不接 ...
- 「LuoguP3191」 [HNOI2007]紧急疏散EVACUATE(最大流
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是’.’,那么表示这是一块空地:如果是’X’,那么表示这是一面墙,如果是’D’,那么表示这是一 ...
- python中为什么需要使用“if __name__ == '__main__'”语句
首先用最简洁的语言来说明一下 if __name__ == '__main__': 的作用:防止在被其他文件导入时显示多余的程序主体部分. 先举个例子,如果不用 if __name__ == '__m ...