日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

D. Tavas and Malekas DFS模拟 + kmp + hash || kmp + hash

發布時間:2023/10/11 综合教程 82 老码农
生活随笔 收集整理的這篇文章主要介紹了 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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。