天天看点

HiHo #1032 : 最长回文子串 【Manacher算法】

#1032 : 最长回文子串

1000ms

1000ms

64MB

描述

   小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。

Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”

   小Ho奇怪的问道:“什么叫做最长回文子串呢?”

“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”

   小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?

先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”

​​提示一​​ 

​​提示二​​ 

​​提示三​​ 

​​提示四​​

样例输入

3

abababa

aaaabaa

acacdas

样例输出

7

5

3

-.-Manacher算法-.-手生了,中间码错了。。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char ch[1001000],cc[2002000];
int shu[2001000];
int ll,ans;
void slove()
{
  shu[0]=1;
  int zhong;
  zhong=ans=0;
  for (int i=1;i<ll;i++)
  {
    <span style="color:#ff0000;">if (zhong+shu[zhong]>i)
      shu[i]=min(shu[2*zhong-i],zhong+shu[zhong]-i);</span>
    else
      shu[i]=1;
    while (i-shu[i]>-1&&cc[i+shu[i]]==cc[i-shu[i]])
      shu[i]++;
    if (i+shu[i]>zhong+shu[zhong])
      zhong=i;
    if (shu[i]>ans)
      ans=shu[i];
  }
  return ;
}
int main()
{
  int n;scanf("%d",&n);
  while (n--)
  {
    scanf("%s",ch);
    ll=strlen(ch);
    cc[0]='#';int lp=1;
    for (int i=0;i<ll;i++)
    {
      cc[lp++]=ch[i];
      cc[lp++]='#';
    }
    ll=lp;
    cc[lp++]=0;
    slove();
    printf("%d\n",ans-1);
  }
  return 0;
}