csuoj 1328: 近似回文词

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1328

1328: 近似回文词

Time Limit: 1 Sec  Memory Limit: 128 MB

Description

输入一行文本,输出最长近似回文词连续子串。所谓近似回文词是指满足以下条件的字符串:

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] = '';
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
",cas ++ , maxlen , chang[pos] + 1);
75     }
76     return 0;
77 }
View Code

这个是用往两边扩展写的,不会存在超时!!!

 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
",T++,a,start+1);
64     }
65   return 0;
66 }
View Code
原文地址:https://www.cnblogs.com/jeff-wgc/p/4458509.html