1258 - Making Huge Palindromes
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.
题意:给定字符串,只能向右边添加任意字符,问使该字符串成为回文串的最小长度是多少;
思路:假设添加过字符后的字符串构成了回文串,那么将串倒置之后的串与原串相同,假设原串长度为len,新串长度为L,也就是说len-1之后的字符都是新添上去的,那么倒置之后的串的0-L-1-(len-1)-1是新添上的,那么中间的部分是原串本来就有的,两串对比=中间的部分回文了,只要找出包含原串最后一位字符的最长回文串的长度,新添字符的长度既可以求出来,再加原串长度即可,求包含最后一个字符的最长回文串的长度操作其实很简单:Manacher从左向右扫描,然后维护mx,我们找到第一个使mx>=新串长度的id返回p[id]-1就是元字符串,注意mx维护的是开区间,即不包括mx这个字符;
失误:想到上述思路之后,我直接用Manacher求最大回文串长度,然后输出(len<<1)减去他,WA了两次才意识到如果最长回文串没有包括最后一个字符的话就错了,因为只能向右边添加字符,如果最长回文串没有包括最后一个字符的话就说明前面没有一个字符和最后有一个字符对称,再添加多少字符也是没用的;
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=3*1e6+66;
char str[MAXN],S[MAXN]; int p[MAXN];
int Manacher(char *S)
{
int id=0,mx=0,i=0,ans=0;
int len=strlen(S);
for(i=1;S[i];++i){
p[i]=mx>i?min(mx-i,p[(id<<1)-i]):1;
while(S[i+p[i]]==S[i-p[i]]) ++p[i];
if(i+p[i]>mx) {
mx=i+p[i];
id=i;
}
if(mx>(len-1)) return p[id]-1;
}
}
int main()
{
int T,i,Kase=0;
scanf("%d",&T);
while(T--)
{
scanf("%s",str);
S[0]='$'; S[1]='#';
for(i=0;str[i];++i)
{
S[(i+1)<<1]=str[i];
S[(i+1)*2+1]='#';
}
S[(i+1)<<1]='\0';
int ans=Manacher(S),len=strlen(str);
printf("Case %d: %d\n",++Kase,len-ans+len);
}
return 0;
}