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;
}