Codeforces 526D Om Nom and Necklace kmp+hash

本文详细介绍了解决POJ1961问题的两种方法:利用KMP算法寻找前缀循环节,以及通过哈希加二分查找求解A的最长长度。提供了一种优化字符串匹配的解决方案。

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

题目链接:点击打开链接

题意:

给出长度为n的字符串,常数k

下面一个长度为n的字符串。

问:

for(int i = 1; i <= n; i++){

字符串的前i个字符 能否构成 形如A+B+A+B+A+B+A的形式,其中A有k+1个,B有k个 A和B是2个任意的字符串(也可以为空串)

若可以构成则输出1,否则输出0

}

思路:

POJ1961 

先用kmp求一个前缀循环节,。

我们观察 ABABABA => AB, AB, AB, A 所以前缀循环节有K个,而后面的A是尽可能地和AB长度接近,所以hash+二分求A的最长长度。


思路2:

直接枚举AB串的长度,然后二分A串的长度即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
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');
}
using namespace std;
const int N = 1000005;
typedef long long ll;
typedef unsigned long long ull;

const int maxn = 2000 * 1000 + 100, base1 = 131, base2 = 127;
const int mod = 1000000007;

int hash1[maxn], hash2[maxn], p1[maxn], p2[maxn];
inline int get(int l, int r){
	l--;
	int ret = hash1[r] - 1LL * hash1[l] * p1[r - l ] % mod;
	if (ret<0)
		ret += mod;
	return ret;
}
int n, k, dp[N];
char s[N];

void work(){
	memset(dp, 0, sizeof dp);
	for (int y = n / k; y; y--){
		int len = y*k;
		if (dp[len] != 0)continue;
		ull now = get(1, y);
		bool ok = true;
		for (int j = 2; j <= k && ok; j++)
		{
			if (get(j*y - y + 1, j*y) != now)
				ok = false;
		}
		if (ok)dp[len]++;
		else {
			continue;
		}
		int las = len;

		int l = len + 1, r = min(len + y, n);
		while (l <= r){
			int mid = (l + r) >> 1;
			if (get(1, mid - len) == get(len + 1, mid)){
				las = max(las, mid);
				l = mid + 1;
			}
			else r = mid - 1;
		}
		dp[las + 1] --;
	}
}
int hehe;
int haha;
int main(){
	p1[0] = 1;
	for (int i = 1; i<maxn; i++)
		p1[i] = 1LL * p1[i - 1] * base1%mod;
	scanf("%d%d", &n, &k);
	scanf("%s", s + 1);
	for (int i = 1; i <= n; i++)
		hash1[i] = (1LL * hash1[i - 1] * base1 + s[i]) % mod;
	if (k > n){ while (n-- > 0)putchar('0'); puts(""); return 0; }
	work();
	int now = 0;
	for (int i = 1; i <= n; i++){
		now += dp[i];
		putchar('0' + (now>0));
	}
	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、付费专栏及课程。

余额充值