题目:http://hihocoder.com/problemset/problem/1032
-
3 abababa aaaabaa acacdas
样例输出
-
7 5 3
描述
小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。
这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”
小Ho奇怪的问道:“什么叫做最长回文子串呢?”
小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”
小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?
小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”
提示一 提示二 提示三 提示四#include<iostream>
#include<string.h>
const long int LL=1000000;//max length
char input[LL];
char inputInsert[2 * LL + 2];
inline long int min(long int a, long int b)
{
return a > b ? b : a;
}
long int Calculate(char* str,long int length)
{
if (length <= 3)
return 1;
long int* F = new long int[length];
F[0] = 1;
F[1] = 3;
long int maxRight = 1;
long int result = F[1];
long int position = 1;
for (long int i = 2; i < length; ++i)
{
if (F[maxRight] / 2 + maxRight>i)//最右边超过i
F[i] = min(F[2 * maxRight - i], F[maxRight] - 2 * (i - maxRight));
else F[i] = 1;
//继续比对,看看后面是否还符合条件
int k = F[i]/2+1;
while ((i + k) < length && (i - k) >= 0 && str[i + k] == str[i - k])
{
++k;
F[i] = F[i] + 2;
}
if (F[maxRight] / 2 + maxRight < F[i] / 2 + i)//更新最右边的边界
maxRight = i;
if (result < F[i])
{
result = F[i];
position = i;
}
}
delete[] F;
if (str[position] == '$')
result /= 2;
else
{
result = (result / 4)*2+1;//这个不能简化,要先除以4,再乘以2,不能直接除以2
//result = result /2+1;
}
return result;
}
int main()
{
int N;
std::cin >> N;
for (int i = 0; i < N; ++i)
{
//scanf_s("%s", input);
std::cin >> input;
long int length = strlen(input);
for (long int i = 0; i < length; ++i)
{
inputInsert[2 * i] = '$';
inputInsert[2 * i + 1] = input[i];
}
inputInsert[2 * length] = '$';
long int result = Calculate(inputInsert, 2 * length+1);
std::cout << result << std::endl;
}
return 0;
}