题目
注意要选好先判断左指针还是右指针可以节省不必要的操作。
最长的指定瑕疵度的元音子串
hash算法、双指针
题目描述
定义:开头和结尾都是元音字母(aeiouAEIOU)的字符串为元音字符串,其中混杂的非元音字母数量为瑕疵度。比如:
“a”、“aa”是元音字符串,其瑕疵度都为0
“aiur”不是元音字符串(结尾不是元音字符)
“abira”是元音字符串,其瑕疵度为2
给定一个字符串,请找出指定瑕疵度的最长元音字符子串,并输出其长度,如果找不到满足条件的元音字符子串,输出0.
子串:字符串中任意个连续的字符组成的子序列称为该字符串的子串
解答要求
时间限制:1000ms,内存限制:256MB
输入
首行输入是一个整数,表示预期的瑕疵度flaw,取值范围[0,65535]。
接下来一行是一个仅由字符a-z和A-Z组成的字符串,字符串长度(0,65535]。
输出
输出为一个整数,代表满足条件的元音字符子串的长度。
样例
输入样例1
0
asdbuiodevauufgh
输出样例1
3
提示样例1
满足条件的最长元音字符子串有两个,分别为uio和auu,长度为3。
输入样例2
2
aeueo
输出样例2
0
提示样例2
没有满足条件的元音字符子串,输出0.
输入样例3
1
aabeebuu
输出样例3
5
提示样例3
满足条件的最长元音字符子串有两个,分别为aabee和eebuu,长度为5
一、问题分析
首先读题,仔细看描述中的内容,发现需求是
1.定义:开头和结尾都是元音字母(aeiouAEIOU)的字符串为元音字符串,
2.其中混杂的非元音字母数量为瑕疵度。
比如:“a”、“aa”是元音字符串,其瑕疵度都为0
“aiur”不是元音字符串(结尾不是元音字符)
“abira”是元音字符串,其瑕疵度为2
3.给定一个字符串,请找出指定瑕疵度的最长元音字符子串,并输出其长度,如果找不到满足条件的元音字符串,输出0.
4.子串:字符串中任意个连续的字符组成的子序列称为该字符串的子串
5.输入:首行输入是一个整数,表示预期的瑕疵度flaw,取值范围[0,65535]。
接下来一行是一个仅由字符a-z和A-Z组成的字符串,字符串长度(0,65535]。
6.输出:输出为一个整数,代表满足条件的元音字符子串的长度。
二、解题思路
1.首先找到满足条件的(瑕疵度)子串
2.在满足瑕疵度的基础上,测量子串的长度
3.如果长度大于上一个满足条件的子串,更新长度
4.需要记录每个瑕疵和瑕疵之间的元音字符数量
5.这样的话,每次减去前面的元音字符数量加上后面的元音字符数量就是字符串的长度了。
三、具体步骤
使用的语言是C
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define max(a,b) (a > b ? a : b)
bool isVowel(char a) {
return (a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u' || a == 'A' ||
a == 'E' || a == 'O' || a == 'U');
}
int main() {
int flaw;
scanf("%d", &flaw);
char input[65537];
scanf("%s", input);
int len = strlen(input);
int maxcount = 0;
if (flaw == 0) {
for (int i = 0; i < len; i++) {
int tempcount = 0;
while (i < len && isVowel(input[i])) {
tempcount++;
i++;
}
maxcount = max(tempcount, maxcount);
}
} else if (flaw == 1) {
int flawcount = 0;
int half = 0;
int half2 = 0;
for (int i = 0; i < len; i++) {
int tempcount = 0;
while (i < len && isVowel(input[i])) {
tempcount++;
i++;
}
if (flawcount == 0 && !isVowel(input[i])) {
flawcount = 1;
tempcount++;
half = 0;
while (i < len && isVowel(input[i])) {
half++;
i++;
}
maxcount = max(tempcount + half, maxcount);
} else if (flawcount == 1 && !isVowel(input[i])) {
half2 = tempcount; // 后半部分元音字母
maxcount = max(half + half2 + 1, maxcount);
half = half2;
}
}
} else { // 如果瑕疵数量大于1个
int before[100] = {0};
int middle = 0;
int after = 0;
int flawcount = 0;
int beforeidx =
0; // 记录每个非元音字符之前的元音字符数量的索引
int counttime = 0; // 记录第几次对比求最大值
for (int i = 0; i < len; i++) {
int tempcount = 0;
while (isVowel(input[i])) {
tempcount++;
i++;
// printf("统计了%d个元音字符\n", tempcount);
}
if (flawcount == 0) {
before[beforeidx++] = tempcount;
// printf("第%d个瑕疵和上一个瑕疵之间有%d个元音字符\n", beforeidx - 1, tempcount);
flawcount++;
// printf("在第一个非元音字符之前有%d个元音字符\n", before[beforeidx - 1]);
} else if (flawcount < flaw) {
if (i < len && !isVowel(input[i])) {
// printf("找到下一个非元音字符,和上一个非元音字符之间有%d个元音字符\n", tempcount);
flawcount++;
before[beforeidx++] = tempcount;
// printf("第%d个瑕疵和上一个瑕疵之间有%d个元音字符\n", beforeidx - 1, tempcount);
middle += tempcount;
} else if (i == len) {
// printf("到达字符串末尾,未找到满足数量的非元音字符,找到的数量是%d\n", flawcount);
printf("0\n");
return 0;
}
if (flawcount == flaw) {
// printf("第一次满足瑕疵数\n");
tempcount = 0;
while (isVowel(input[i])) {
tempcount++;
i++;
}
after = tempcount;
// printf("第一次满足瑕疵之后的元音字符数量是%d\n", after);
before[beforeidx++] = tempcount;
// printf("第%d个瑕疵和上一个瑕疵之间有%d个元音字符\n", beforeidx - 1, tempcount);
// printf("这次找到的第%d个瑕疵\n",beforeidx - 1);
maxcount = max(before[counttime] + middle + after + flawcount, maxcount);
// printf("counttime is %d\n", counttime);
// printf("before[counttime++]的值是%d + middle的值是%d + after的值是%d + flawcount的值是%d, maxcount的值是%d\n", before[counttime], middle, after, flawcount, maxcount);
counttime++;
middle = middle - before[counttime] + after;
}
} else if (flawcount == flaw) {
after = tempcount;
before[beforeidx++] = tempcount;
maxcount = max(before[counttime] + middle + after + flawcount, maxcount);
counttime++;
middle = middle - before[counttime] + after;
}
}
}
printf("%d\n", maxcount);
}