csuoj 1328: 近似回文词
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1328
1328: 近似回文词
Time Limit: 1 Sec Memory Limit: 128 MBDescription
输入一行文本,输出最长近似回文词连续子串。所谓近似回文词是指满足以下条件的字符串:
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
HINT
Source
分析:
暴力模拟(有人说会有TLE,但是我就AC啦,RP吧)即可, 还可以从某个点往两边分别比较。
AC代码:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <iostream> 4 #include <string.h> 5 #include <string> 6 #include <math.h> 7 #include <stdlib.h> 8 #include <queue> 9 #include <stack> 10 #include <set> 11 #include <map> 12 #include <list> 13 #include <iomanip> 14 #include <vector> 15 #pragma comment(linker, "/STACK:1024000000,1024000000") 16 #pragma warning(disable:4786) 17 18 using namespace std; 19 20 const int INF = 0x3f3f3f3f; 21 const int MAX = 2000 + 10; 22 const double eps = 1e-8; 23 const double PI = acos(-1.0); 24 25 char str[MAX] , hw[MAX]; 26 int chang[MAX]; 27 int k; 28 29 int main() 30 { 31 int cas = 1; 32 while(~scanf("%d",&k)) 33 { 34 getchar(); 35 gets(str); 36 int len = strlen(str); 37 int cnt = 0; 38 for(int i = 0 ;i < len;i ++) 39 { 40 if((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z')) 41 { 42 char c = str[i]; 43 if(c >= 'A' && c <= 'Z') 44 c = c - 'A' + 'a'; 45 chang[cnt] = i; 46 hw[cnt ++] = c; 47 } 48 } 49 hw[cnt] = '\0'; 50 int maxlen = 1 , pos = 1; 51 for(int j = cnt;j >= 1;j --) 52 for(int i = 0;i + j - 1 < cnt;i ++) 53 { 54 int st = i + j - 1,cnt = 0; 55 int len = chang[st] - chang[i] + 1; 56 if(len < maxlen) 57 continue; 58 for(int l1 = i,l2 = st;l1 < l2;l1 ++ , l2 --) 59 { 60 if(hw[l1] != hw[l2]) 61 cnt += 2; 62 if(cnt > 2 * k) 63 break; 64 } 65 if(cnt <= 2 * k) 66 { 67 if(maxlen < len || (maxlen == len && i < pos)) 68 { 69 maxlen = len; 70 pos = i; 71 } 72 } 73 } 74 printf("Case %d: %d %d\n",cas ++ , maxlen , chang[pos] + 1); 75 } 76 return 0; 77 }
这个是用往两边扩展写的,不会存在超时!!!
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<string> 7 #include<cmath> 8 #include<cctype> 9 using namespace std; 10 char s[1010],s1[1010]; 11 int ans[1010]; 12 int main() 13 { 14 int T=1,k,i,j; 15 while(~scanf("%d",&k)) 16 { 17 int a = 0,kk=0,start = 0,flag; 18 getchar(); 19 gets(s); 20 int len = strlen(s); 21 for( i=0;i<len;i++) 22 { 23 if(isalpha(s[i])) //判断是否是字母 24 { 25 ans[kk] = i; 26 s1[kk] = toupper(s[i]);//转换成大写字母 27 kk++; 28 } 29 } 30 for( i=0; i<kk; i++) 31 { 32 flag = 0; 33 for( j=0;i-j>=0 && i+j<kk; j++)//奇数个时; 34 { 35 if(s1[i-j]!=s1[i+j]) 36 flag++; 37 if(flag>k) 38 break; 39 } 40 j--; 41 if(ans[i+j]-ans[i-j]+1>a) 42 { 43 a = ans[i+j]-ans[i-j]+1; 44 start = ans[i-j]; 45 } 46 flag = 0; 47 for( j=0; i-j>=0 && i+j+1<kk; j++)//偶数个时 48 { 49 if(s1[i-j]!=s1[i+j+1]) 50 flag ++; 51 if(flag>k) 52 break; 53 } 54 j--; 55 if(j<=-1) 56 continue; 57 if(ans[i+j+1]-ans[i-j]+1>a) 58 { 59 a = ans[i+j+1]-ans[i-j]+1; 60 start = ans[i-j]; 61 } 62 } 63 printf("Case %d: %d %d\n",T++,a,start+1); 64 } 65 return 0; 66 }
悠游天地间 all rights reserved. © 2013 -- 1 << 64