A - 近似回文词
输入一行文本,输出最长近似回文词连续子串。所谓近似回文词是指满足以下条件的字符串:
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 Input1Wow, it is a Race cat!0abcdefg0Kitty: Madam, I'm adam.Sample Output
Case 1: 8 3Case 2: 1 1Case 3: 15 8
Hint
这道题我刚开始的想法就是硬搜,然后不出意外的超时了。然后优化了一下双向搜索过了......(他要求显示的位置是原来的位置这是一个坑.....专门开了一个数组来记录)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
char pt[2000],s[2000];
int ss[2000];
int n,m,q,x,y,t=1,k,flag,f,ans,sum;
while(~scanf("%d\n",&k))
{
flag=0;ans=0;x=0;
gets(pt);
int len=strlen(pt);
for(int i=0;i<len;i++){
if(isalpha(pt[i])){//判断是不是字母;
ss[flag]=i;//记录位置
s[flag]=toupper(pt[i]);//转换成小写的;
flag++;
}
}
int j=0;
for(int i=0;i<flag;i++){
sum=0;//记录有几个不同
for(j=0;i-j>=0&&i+j<flag;j++){
if(s[i-j]!=s[i+j])sum++;
if(sum>k)break;
}
j--;//因为超出的时候输出j,所以j要减1;
if(ss[i+j]-ss[i-j]+1>ans){
ans=ss[i+j]-ss[i-j]+1;
x=ss[i-j];
}//偶数个的情况
sum=0;
for(j=0;i-j>=0&&i+j+1<flag;j++){
if(s[i-j]!=s[i+j+1])sum++;
if(sum>k)break;
}
j--;
if(j<=-1)continue;
if(ss[i+j+1]-ss[i-j]+1>ans){
ans=ss[i+j+1]-ss[i-j]+1;
x=ss[i-j];
}
}
printf("Case %d: %d %d\n",t++,ans,x+1);
}
return 0;
}