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 + 20; const int MOD = 1e9 + 7; int tonext[maxn]; int ret; char str[maxn]; char sub[maxn]; void dfs(int cur, int k, int from) { if (k < 0) return; if (k == 0) { 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 + 1; str[cur] = sub[from]; dfs(cur + 1, k - 1, from + 1); tonext[cur] = ret; } } int a[maxn]; bool HASH[maxn]; int kmpnext[maxn]; void get_next(char sub[], int lensub) { int i = 1, j = 0; kmpnext[1] = 0; while (i <= lensub) { if (j == 0 || sub[i] == sub[j]) { kmpnext[++i] = ++j; } else j = kmpnext[j]; } return; } void kmp(int lenstr, int lensub) { int i = 1, j = 1; while (i <= lenstr) { if (j == 0 || str[i] == sub[j]) { ++i; ++j; } else j = kmpnext[j]; if (j == lensub + 1) { HASH[i - lensub] = true; j = kmpnext[j]; } } return; } void work() { int lenstr, m; scanf("%d%d", &lenstr, &m); for (int i = 1; i <= lenstr; ++i) { tonext[i] = i; str[i] = 'A'; // printf("f"); } // printf("%c ", str[1]); scanf("%s", sub + 1); int lensub = strlen(sub + 1); for (int i = 1; i <= m; ++i) { scanf("%d", &a[i]); dfs(a[i], lensub, 1); } str[lenstr + 1] = '