lightoj 1258 - Making Huge Palindromes 【Manacher】

来源:互联网 发布:网络平台招商加盟 编辑:程序博客网 时间:2024/05/16 06:24

1258 - Making Huge Palindromes
PDF (English)StatisticsForum
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.


PROBLEM SETTER: JANE ALAM JAN

自己AC的, 对Manacher理解加深了。

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


思路:用Manacher算法求出原串s的最大回文子串的长度ans,如果ans == len(串长),输出ans。反之,我们必须要在末尾添加字符来构成回文字符串,考虑最后一个字符,我们只需要找出包含它的最长回文子串的长度Mlen,结果就为len - Mlen + len。
求解Mlen,可以直接在Manacher中进行。用str存储新串,根据数组p的定义,只有p[i] + i - 1==l-1(l新串长)时才说明 以字符str[i]为中心的回文字符串包含最后一个字符,这个情况下更新Mlen的值。

算法时间复杂度o(n)。


AC代码:


#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 1001000using namespace std;char s[MAXN], str[MAXN*2];int p[MAXN*2];int ans, Mlen;int l;void Manacher(char *T){    int len = strlen(T);    l = 0;    str[l++] = '@'; str[l++] = '#';    for(int i = 0; i < len; i++)    {        str[l++] = T[i];        str[l++] = '#';    }    str[l] = 0;    int mx = 0, id = 0;    ans = Mlen = 0;    for(int i = 0; i < l; i++)    {        if(mx > i)            p[i] = min(p[2*id-i], mx-i);        else            p[i] = 1;        while(str[i+p[i]] == str[i-p[i]])            p[i]++;        if(i + p[i] > mx)        {            mx = i + p[i];            id = i;        }        ans = max(ans, p[i]-1);        if(p[i] - 1 + i == l - 1)//包含最后一个字符 更新            Mlen = max(Mlen, p[i]-1);    }}int kcase = 1;void solve(char *s){    Manacher(s);    int len = strlen(s);    if(ans == len)        printf("Case %d: %d\n", kcase++, ans);    else        printf("Case %d: %d\n", kcase++, len - Mlen + len);}int main(){    int t;    scanf("%d", &t);    while(t--)    {        scanf("%s", s);        solve(s);    }    return 0;}





1 0