1258 - Making Huge Palindromes

PDF (English) Statistics Forum
Time Limit: 1 second(s) Memory Limit: 32 MB
A string is said to be a palindrome if it remains same when read backwards. So, 'abba', 'madam' both are palindromes, but 'adam' is not.

Now you are given a non-empty string S, containing only lowercase English letters. The given string may or may not be palindrome. Your task is to make it a palindrome. But you are only allowed to add characters at the right side of the string. And of course you can add any character you want, but the resulting string has to be a palindrome, and the length of the palindrome should be as small as possible.

For example, the string is 'bababa'. You can make many palindromes including

bababababab

babababab

bababab

Since we want a palindrome with minimum length, the solution is 'bababab' cause its length is minimum.

Input
Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with a line containing a string S. You can assume that 1 ≤ length(S) ≤ 106.

Output
For each case, print the case number and the length of the shortest palindrome you can make with S.

Sample Input
Output for Sample Input
4

bababababa

pqrs

madamimadam

anncbaaababaaa

Case 1: 11

Case 2: 7

Case 3: 11

Case 4: 19

Note
Dataset is huge, use faster I/O methods.



题意:给你一个串s,你可以在末尾添加任意数量的字符得到一个回文字符串,问你回文字符串的最小长度。

思路:回文串的问题很容易想到Manacher算法解决。但是这道题要注意的是我们统计的应该是包括最后一个字符的最大回文长度,也就是 i+Mp[i] == 2*len+2

为什么呢?

因为如果是中间部分的回文我们没法利用,通过添加字符使其变成回文。但是包括最后一个字符的我们就可以利用了。

 

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000005
18 #define mod 1000000007
19 using namespace std;
20 char Ma[MAXN*2];
21 int Mp[MAXN*2];
22 char s[MAXN];
23 
24 void Manacher(char s[],int len)
25 {
26     // 预处理
27     int l = 0;
28     Ma[l++] = '$';
29     Ma[l++] = '#';
30     for (int i=0;i<len;i++)
31     {
32         Ma[l++] = s[i];
33         Ma[l++] = '#';
34     }
35     Ma[l++] = 0;
36     //根据Mp[i-1]递推出Mp[i]
37     int mx = 0;  // i-1的最右端
38     int id = 0;  // i-1的中心
39     for (int i=0;i<l;i++)
40     {
41         Mp[i] = mx>i?min(Mp[2*id-i],mx-i):1;
42         while (Ma[i+Mp[i]] == Ma[i-Mp[i]])
43             Mp[i]++;
44         if (i+Mp[i]>mx)
45         {
46             mx = Mp[i]+i;
47             id = i;
48         }
49     }
50 }
51 
52 int main()
53 {
54     int t;
55     scanf("%d",&t);
56     int k=1;
57     while (t--)
58     {
59         scanf("%s",s);
60         getchar();
61         int len = strlen(s);
62         int ans = 0;
63         Manacher(s,len);
64         for (int i=0;i<2*len+2;i++)
65         {
66             if (i+Mp[i] == 2*len+2)
67                 ans = max(ans,Mp[i]-1);
68         }
69        printf("Case %d: %d\n",k++,2*len-ans);
70     }
71     return 0;
72 }