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

此爲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會TLE
						flag = 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代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章