Codeforces 536B Tavas and Malekas 求自身首尾的重叠位置 KMP

本文讨论了如何使用KMP算法解决特定条件下的字符串匹配问题,详细介绍了算法实现步骤,并通过实例展示了其实用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:点击打开链接

题意:

用小写字母构造n长的串S,m个要求

字符串P

下面m个位置。a1, a2···am(输入有序)

要使得字符串S的以ai 开头且后面是一个P串。

问构造的方法数

思路:

实际上,对于ai, ai+1 ,两个位置,如果这两个位置会相互影响(即 ai+1 - ai < len) 

复制一个和P一样的串P‘

把P放在ai位置,把P‘放在ai+1位置,那么只需要判断一下 P的后半段是否和P‘的前半段匹配即可。

也就是P’的哪些位置是和P的尾部相同的。

KMP求出这些位置放到set里。

然后就是简单的判断了

#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <map>
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x <0) {
		putchar('-');
		x = -x;
	}
	if (x>9) pt(x / 10);
	putchar(x % 10 + '0');
}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;

int f2[N], len;
char s1[N], s2[N];
void getFail(int *f, char *P){
	f[0] = f[1] = 0;
	for (int i = 1; i < len; i++){
		int j = f[i];
		while (j&&P[i] != P[j])j = f[j];
		f[i + 1] = P[i] == P[j] ? j + 1 : 0;
	}
}

set<int>s;
void KMP(int *f, char *S1, char *S2){
	getFail(f, S2);
	int j = 0, i = 0;
	while (i <= len)
	{
		while (j && S1[i] != S2[j]) j = f[j];
		i++, j++;
	}
	for (int i = len; f[i]; i = f[i])
		s.insert(len-f[i]);
}
int m, n;
bool v[N];
int main() {
	while (cin >> n){
		rd(m);
		scanf("%s", s1);
		while (m--){
			int u; rd(u);
			v[u] = true;
		}
		len = strlen(s1);
		memcpy(s2, s1, sizeof s1);
		KMP(f2, s1, s2);

		ll ans = 1;
		for (int i = 1, last = -1e7; i <= n; i++){
			if (v[i] == false && i - last >= len){
				ans *= 26LL;
				if (ans >= mod)ans %= mod;
			}
			else if (v[i] == true){
				if (i - last < len && !s.count(i-last)){
					ans = 0; break;
				}
				last = i;
			}
		}
		pt(ans%mod); puts("");
	}
	return 0;
}


### 关于 Codeforces 平台上的 KMP 算法练习题目 对于希望在 Codeforces 上找到有关 KMP (Knuth-Morris-Pratt) 字符串匹配算法的练习题目的选手来说,可以关注几个特定标签下的问题。通常这些题目会被标记为 "strings" 或者更具体地标记为 "string suffix structures"[^1]。 为了帮助更好地理解如何查找适合的练习题目,在此提供一段 Python 代码用于模拟访问 API 获取带有指定标签的问题列表: ```python import requests def fetch_problems(tag, platform="codeforces"): url = f"https://{platform}.com/api/problemset.problems?tags={tag}" response = requests.get(url) if response.status_code != 200: raise Exception(f"Failed to retrieve data from {platform}") json_data = response.json() problem_list = [] for index, item in enumerate(json_data['result']['problems']): name = item["name"] rating = item.get('rating', 'N/A') contest_id = item["contestId"] index = item["index"] problem_info = { "Name": name, "Rating": rating, "Link": f"{platform}.com/contest/{contest_id}/problem/{index}" } problem_list.append(problem_info) return problem_list[:5] # Example usage with the tag related to string processing or specifically KMP pattern matching. kmp_related_tag = "strings" fetched_problems = fetch_problems(kmp_related_tag) for prob in fetched_problems: print(prob) ``` 这段脚本会调用 Codeforces 的公开 API 来获取前五个与字符串处理相关的编程挑战链接,并打印出来供参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值