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 dierent 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" dier 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
 posted on 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号