题解:P13291 [GCJ 2013 #1C] Consonants

题目解释

这是一道看似黄题,实则是黄题的字符串相关的题目。

思路

1. 寻找满足要求的字符串

遍历字符串,找到所有长度至少为 的连续辅音字母段。对于每个这样的段,记录其起始和结束位置。

2. 计算有效子串

对于每个长度为m的连续辅音段 ,计算包含至少 个连续辅音字母的子串数量。具体来说,假设这个连续辅音段从位置 (共 个字符),那么在这个段中,有效的子串必须包含至少 个连续的辅音字母。这些子串的起始位置可以在 之前或等于 ,结束位置可以在 之后或等于 ,只要子串覆盖至少 个连续的辅音字母。

  • 解释(

选 ght。

straighta
可选可选可选可选可选必选必选必选可选

左边有 个可选,在 左边有 个可选,所以左端点有 种选择,右端点有 种选择,所以一共有 种选择。

3 .避免重复计算:

确保每个子串只被计算一次。可以通过滑动窗口的方式,维护最近的满足条件的辅音段,并计算新子串的数量。

  • 解释(

选 str 和 ght。

straight
可选1可选1可选1可选1可选1必选1必选1必选1
必选2必选2必选2可选2可选2可选2可选2可选2

在选 str 的时候会取到 straight,而且在选 ght 的时候也会取到 straight,所以要去重。

代码

#include <bits/stdc++.h>
#define int long long
#define run_fast ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
string s;
int n;
bool isVowel(char c) {
	return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
signed main() {
	run_fast;
	int T;
	cin >> T;
	for (int j = 1; j <= T; j++) {
		cin >> s >> n;
		int ans = 0, con = 0, last = -1;
		for (int i = 0; i < s.size(); i++) {
			if (!isVowel(s[i])) {
				con++;
				if (con >= n) {
					int start = i - n + 1, left = start - last, right = s.size() - i;
					ans += left * right;
					last = start;
				}
			} else {
				con = 0;
			}
		}
		cout << "Case #" << j << ": " << ans << "\n";
	}
	return 0;
}
//var code = "c3d5192f-68a0-4517-859b-34fd1dd4f60c"
posted @ 2025-07-22 15:29  liketaem  阅读(7)  评论(0)    收藏  举报  来源