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 模板: / ...
随机推荐
- java序员必备的十大技能
想成为一名出色的Java程序员么?本文将为大家重点介绍程序员必备的十大技能,成就您的梦想. 1.语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样 ...
- axis、xfire、CXF 、JWS
1.JWS是Java语言对WebService服务的一种实现,用来开发和发布服务.而从服务本身的角度来看JWS服务是没有语言界限的.但是Java语言为Java开发者提供便捷发布和调用WebServic ...
- gravity layout_gravity
gravity:控制当前视图的内容/子view layout_gravity:控制视图本身
- SpringBoot启动跟踪
程序启动入口 @SpringBootApplication public class Chapter001Application { public static void main(String[] ...
- YTU 2391: 求素数
2391: 求素数 时间限制: 1 Sec 内存限制: 128 MB 提交: 116 解决: 3 题目描述 设计一个程序,输出所有小于等于n(n为一个大于2的正整数)的素数. 要求:(1)每行输出 ...
- (转)windows下的Expdp、Impdp使用
1 .Expdp windows下导出截图示范 2.impdp windows下导入截图示范 Impdp system/eas directory=EASBAK dumpfile=stjt_10060 ...
- 基于C#实现Windows服务状态启动和停止服务的方法
网址:http://www.jb51.net/article/89230.htm
- SPOJ:Elegant Permuted Sum(贪心)
Special Thanks: Jane Alam Jan*At moment in University of Texas at San Antonio - USA You will be give ...
- iOS添加弹出菜单
最近接触的项目需要实现一个弹出窗,类似于点击微信navigation bar右上角的bar button所展现的弹出窗,最终效果如下: Demo代码存放在https://github.com/LuoD ...
- 「LuoguP1122」 最大子树和
Description 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是 ...