codeforces 535D. Tavas and Malekas----#299div2D

来源:互联网 发布:自动编程软件 编辑:程序博客网 时间:2024/05/19 00:09

此为kmp好题


题意:现在已知串p,还知道串s中与p匹配的都有那些位置,问这样的s串共有多少个

思路:这个题就是直接用p把匹配的位置填上就可以了,没有填的位置就是可以变换的,假设有x个位置那么答案就是26^x。需要注意的是重复的地方,如果暴力填的话,复杂度太大,所以可以先求KMP,或者扩展KMP,然后判断重叠的部分会不会有冲突


先把能填的字符都填上,然后通过KMP验证是否符合所有的条件,如果不符合则为0,如果符合则计算26^w,w为s中没有填字符的数量。


#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;int n, m;char ans[1000100];int vis[1000100];char p[1000100];int pre[1000100];int l;int ma[1000100];int mat[1000100];int mmin;/*bool scan_d(int &num)//输入整型  {char in; bool IsN = false;in = getchar();if (in == EOF) return false;while (in != '-' && (in<'0' || in>'9')) {if (in == EOF)return false;in = getchar();}if (in == '-'){ IsN = true; num = 0; }else num = in - '0';while (in = getchar(), in >= '0'&&in <= '9'){num *= 10, num += in - '0';}if (IsN) num = -num;return true;}*/bool cptpf(int prefix[], char p[], int len){int lolp = 0;prefix[0] = prefix[1] = 0;int nocm = 2;for (nocm = 2; nocm < len + 1; nocm++){while (lolp>0 && p[lolp] != p[nocm - 1])lolp = prefix[lolp];if (p[lolp] == p[nocm - 1])lolp++;prefix[nocm] = lolp;if (vis[nocm+mmin-1]){if (nocm == l || lolp == l);else if (lolp < l)return false;else {int rt = lolp;int flag = 0;while (rt>l){rt = prefix[rt];if (vis[rt + mmin - 1]){//没有此处的优化是不能过的,用例41会TLEflag = 1;break;}}if (flag);else if (rt < l)return false;}}}return true;}int main(){int i, j;while (~scanf("%d%d", &n, &m)){scanf("%s", p);if (m == 0){long long w = 1;for (i = 0; i < n; i++){w *= 26;w %= 1000000007;}printf("%I64d\n", w);continue;}memset(ans, '0', sizeof(ans));memset(vis, 0, sizeof(vis));l = strlen(p);mmin = 0x3f3f3f3f;for (i = 1; i <= m; i++){//scan_d(ma[i]);scanf("%d", &ma[i]);if (mmin>ma[i])mmin = ma[i];mat[i] = ma[i] + l - 2;}//sort(ma + 1, ma + m + 1);sort(mat + 1, mat + m + 1);for (i = 1; i <= m; i++){int tr = mat[i];while (tr >= mat[i] - l + 1 && ans[tr] == '0'){ans[tr] = p[tr + l - mat[i] - 1];tr--;}}for (i = 1; i <= m; i++)vis[mat[i] + 1] = 1;int re = cptpf(pre, ans + mmin - 1, n - mmin + 1);if (re == false){printf("0\n"); continue;}long long w = 1;for (i = 0; i < n; i++){if (ans[i] == '0'){w *= 26;w %= 1000000007;}}printf("%I64d\n", w);}return 0;}



强行用kmp调了好久才过去

有几个注意点

1、1e9+7这种数以后还是用define 或者const吧,我才不会说,一开始竟然写成了1000000009.。。

2、注意代码中注释的优化

3、TLE了要先看看输入挂是不是能起到效果,不能盲目使用

4、个人感觉这道题如果用EKMP会好一点吧,不过EKMP学的不怎么滴,学完来加EKMP代码

1 0
原创粉丝点击