Description
给定一个由英文字母组成的字符串,求出一个子串,满足如下要求:该子串所包含的元音字母(a,e,i,o,u)的个数不大于辅音字母的个数的两倍。
你的任务是找到最长的满足要求的子串,输出其长度,并且输出最长的满足条件的子串的个数(区分2个子串是否不同的因素是起始位置和长度)。
Input
输入包括多组数据,每组数据包括一行,每行有一个由英文字母组成的字符串(长度<=200000)。
Output
每组数据输出一行,每行包括2个整数a和b,其中a代表最长子串的长度,b代表最长子串的个数,若不存在这样的子串,则输出“No solution”(不含引号)。
Sample Input
abo
oeis
Sample Output
3 1
3 1
题目链接:http://edu.freefcw.com/problem/show/1594
写了一个最笨的O(n^2)的算法,看到题目中的“长度<=200000”一直不敢提交,认为一定会TLE,想降低复杂度,但是又想不出方法,还是算法功底太弱了。
后来一咬牙,豁出去了,不就是TLE吗,又不会怀孕,提交试试看吧。这次结果WA了,想着可能是字符串中出现了大写字母而程序没有对其进行处理导致的,修改之后再次提交。
结果让我很惊讶,居然AC了,耗时还是0ms,是OJ上的测试用例不靠谱呢还是题目故意吓唬人呢?
先mark一记,想出好方法了再添加上来。如果某位大牛有好的算法,还望不吝赐教,不胜感谢!
#include <stdio.h>
#include <memory.h>
#define MAX 200001
int main(void)
{
char str[MAX];
int status[128];
int i, j, len_1, len_2, len_3, len_4, max_len, count;
memset(status, 0, sizeof(status));
status['a'] = status['A'] = 1;
status['e'] = status['E'] = 1;
status['i'] = status['I'] = 1;
status['o'] = status['O'] = 1;
status['u'] = status['U'] = 1;
while (scanf("%s", str) != EOF)
{
i = max_len = count = 0;
while (str[i] != '\0')
{
j = i;
len_1 = len_2 = len_3 = len_4 = 0;
while (str[j] != '\0')
{
if (status[str[j]] == 0)
{
++len_1;
}
else
{
++len_2;
}
++len_3;
if (len_2 - len_1 <= len_1 && len_4 < len_3)
{
len_4 = len_3;
}
++j;
}
if (len_4 > max_len)
{
max_len = len_4;
count = 1;
}
else if (len_4 == max_len && len_4 != 0)
{
++count;
}
else
{
}
if (len_4 == len_3)
{
break;
}
++i;
}
if (count == 0)
{
printf("No solution\n");
}
else
{
printf("%d %d\n", max_len, count);
}
}
return 0;
}