12656 Almost Palindrome
Given a line of text, nd the longest almost-palindrome substring. A string S is almost-palindrome if
1. S begins and ends with a letter, and
2. a(S) and b(S) have at most 2k positions with di erent characters
Here a(S) is the string after removing all non-letter characters and converting all the letters to
lowercase, b(S) is the reversed string of a(S).
For example, when k = 1, \Race cat" is almost-palindrome, because a(S)=\racecat" and
b(S)=\tacecar" di er at exactly 2 positions.
Input
There will be at most 25 test cases. Each test case contains two lines. The rst line is k (0  k  200).
The second line contains a string with at least one letter and at most 1,000 characters (excluding the
newline character). The string will only contain letters, spaces and other printable characters like (`,'
or `.' etc) and will not start with a whitespace.
Output
For each test case, print the length of the longest almost-palindrome substring and its starting position
(starting from 1). If there is more than one such string, print the smallest starting position.
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

 

题意是给出k以及一条字符串,长度小于10^3,要寻求一个满足要求的子串并且长度尽可能的大,输出这个串的长度以及起始位置。子串的要求是,把这段子串里的非字母字符去掉并且把大写字母改为小写字母之后,设这个精简后的串为a,设把串a反转之后的串为b,然后比较这两个串上有多少个位置的字符不同,不同的数量少于2*K则满足要求。

 

思路果断DP。设dp[i][j],把整条串精简一下后的,第 i 位到第 j 位的不同的字符数。其实从第 i 位到第 j 位的不同数就是 从第 i+1 位 到第 j-1 位上不同的数量,加上判断下第i位跟第j位是否不同 所以得到递推式  

dp[i][j] = dp[i+1][j-1] (第i位和第j位相同)

dp[i][j] = dp[i+1][j-1]+1 (第i位和第j位不同)

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
using namespace std;
const int N = 1010;
int k;
char s[N],let[N];
int dp[N][N],len,n,l[N];

void pre()
{
    len = strlen(s);
    n = 0;
    for(int i=0;i<len;++i)
        if(isalpha(s[i]))
        {
            if(isupper(s[i]))
                s[i]='a'+s[i]-'A';
            let[n]=s[i];
            l[n++]=i;
        }
    for(int i=0;i<=n;++i)
        dp[i][i]=dp[i+1][i]=0;
}

int main()
{
    freopen("case.txt","r",stdin);
    int cas=1;
    while(scanf("%d",&k)!=EOF)
    {
        char tc;
        scanf("%c",&tc);
        gets(s);
        pre();
        int ans = 1,pos = 0;
        for(int ll=1;ll<n;++ll)
            for(int i=0;i+ll<n;++i)
            {
                dp[i][i+ll]=dp[i+1][i+ll-1] + (let[i]!=let[i+ll]);
                if(dp[i][i+ll]<=k)
                {
                    int tmp = l[i+ll]-l[i]+1;
                    if(tmp > ans)
                        ans = tmp , pos = l[i];
                    else if(tmp==ans && pos > l[i])
                        pos = l[i];
                }
            }
        printf("Case %d: %d %d\n",cas++,ans,pos+1);
    }
    return 0;
}

 

 posted on 2014-08-13 21:29  someblue  阅读(415)  评论(0)    收藏  举报