好久没写博客了。。。开学来了学校后总是烦于总结,最近看大家都开始写了,自己才又拾起来。。。
题目:
Description
输入一行文本,输出最长近似回文词连续子串。所谓近似回文词是指满足以下条件的字符串:
1. S 以字母开头,字母结尾
2. a(S)和 b(S)最多有 2k 个位置不同,其中 a(S)是 S 删除所有非字母字符并且把所有字母转化成小写之后
得到的串,b(S)是 a(S)的逆序串。
比如当 k=1 时,Race cat 是一个近似回文词,因为 a(S)=racecat 和 b(S)=tacecar 只有 2 个位置不同。
Input
输入包含不超过 25 组数据,每组数据包含两行。第一行是整数 k(0<=k<=200),第二行为字符串 S,包含
至少一个字母但不超过 1000 个字符(换行符不算)。S 只包含字符、空格和其他可打印字符(比如逗号,句
号),并且不会以空白字符开头。
Output
对于每组测试数据,输出最长近似回文子串的长度和起始位置(S 的第一个字符是位置 1)。如果有多个最
长近似回文子串解,起始位置应尽量小。
Sample Input
1
Wow, it is a Race cat!
0
abcdefg
0
Kitty: Madam, I'm adam.
Sample Output
Case 1: 8 3
Case 2: 1 1
Case 3: 15 8
题意:
这题太像USACO上的那道CALF FLAC了,有一点区别就是他是说给你一个K,那么最长回文串中最多可以有2*k个位置的字母不同。所以叫做近似回文串。
思路:
这题似乎用USACO那题自己的思路有些复杂了,所以就用了那小白书上的方法,分为近似回文串奇数和偶数的情况来写。从中间往两侧找,发现很多字符串的题思路都是从中间往两侧找。这题又被空格坑了,我们oj测试数据输完k后居然又有空格,搞的我一直wa。。。。
代码:
#include<stdio.h>
#include<string.h>
int main()
{
int k,n,p[1000],j,i,o,l=0;
char str[1000],ch[1000];
while (scanf("%d",&k)!=EOF)
{
l++;
int max=0,f=0,t=0;
gets(str);//输入k后的空格。。。。
gets(str);
n=strlen(str);
int m=0;
for ( i=0;i<n;i++)
{
if (str[i]>='a'&&str[i]<='z'){
p[m]=i+1;//记录下字母在原字符串中的位置,以便最后输出。
ch[m++]=str[i];
}
if (str[i]>='A'&&str[i]<='Z'){
p[m]=i+1;
ch[m++]=str[i]-'A'+'a';
}//将字母存起来,并统一转换为大写或小写。
}
f=0;
for (i=0;i<m;i++){
o=k;
for (j=0;i-j>=0&&i+j<m;j++){
if (ch[i-j]!=ch[i+j])
o--;//若有一组不同了,就给k--;
if (o<0)
break;
t=p[i+j]-p[i-j]+1;
if (t>max){
max=t;
f=p[i-j];
}
}//若以当前字母为中心回文串为奇数的时候
o=k;
for (j=0;i-j>=0&&i+j+1<m;j++){
if (ch[i-j]!=ch[i+j+1])
o--;
if (o<0)
break;
t=p[i+j+1]-p[i-j]+1;
if (t>max){
max=t;
f=p[i-j];
}//若以当前字母为中心回文串为偶数的时候
}
}
printf("Case %d: %d %d\n",l,max,f);
}
return 0;
}
注:
刚开始的时候就是认为是n后有个空格却没想太多,突然想起来为何我刚开始用getchar会出错,去搜了一下,才发现了问题,原来getchar在读入字符时以回车结束可是却 不会舍弃回车,会把回车保留在缓冲区,所以,在用getchar的时候读到的字符串的第一个字符就成了回车,而gets读入字符串是也是以回车结束,可是他会舍弃回车,这样读到的第一个字符才是我们输入的。
所以如果一组测试数据后有个空格然后再是回车的话,用scanf(“\n”);和getchar();是不同的,第一种读入了一个空,而第二种则读入了两个空。