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] = '\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 }
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\n",T++,a,start+1);

64     }

65   return 0;

66 }
View Code

 

你可能感兴趣的:(回文)