hdu3068

Posted bennian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu3068相关的知识,希望对你有一定的参考价值。

题意:给出一个字符串,计算其中的最长回文长度

这题字符串长度给到10的5次方,简单的枚举不行。采用manacher算法则可以在O(n)的时间内得出答案。

manacher算法理解:

工具:1、定义了一个数组 r[ i ] 记录的是以i为中心向最左边(或者最右边)的最长回文长度,即回文的半径。

           2、定义整数形的id,记录到目前为止记录的回文所能到的最右边的回文中心。

           3、定义一个maxlen记录最长回文长度

 预处理:在原来的字符串中插入“#”;作用:使插入后的字符串变成奇数长度,便于求出回文中心。

 分析:

 1、i < r [ id ] + id;

    此时分两种:

    1 、r [ i ] = r [ j ]  ( j 为 i 关于 id 的对称点 );

     2、r [ i ] 最小为 r [ id ] +id-i;

  再左右遍历;

 2、i >=r [ id ]+ id;

    这时只能左右遍历了。

 https://www.cnblogs.com/z360/p/6375514.html

具体在这个博客有更详细的分析。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
using namespace std;
#define MAX 110002
int r[2*MAX];
string s,ss;
int init()
{
   int len=s.size();
   ss+=\'!\';//防止溢出
    ss+=\'#\';
   for(int i=0;i<len;i++)
   {
      ss+=s[i];
      ss+=\'#\';
   }
  cout<<ss;
    return ss.size();
}
int manacher(int len)
{
        int id=0;
        int maxlen=0;
     for(int i=2;i<len;i++)
     {
         if(i<r[id]+id)
            r[i]=min(r[2*id-i],r[id]+id-i);
         else
            r[i]=1;
         while(ss[i+r[i]]==ss[i-r[i]])r[i]++;
         if(r[i]+i>r[id]+id)id=i;
         maxlen=max(maxlen,r[i]);
     }
     return maxlen-1;//记得减一
}
int main()
{
  while(cin>>s)
  {
    memset(r,0,sizeof(r));
    ss="";
     int len=init();
    printf("%d\\n",manacher(len));
    getchar();
  }
}
View Code

 

以上是关于hdu3068的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3068 最长回文

HDU 3068 最长回文(manacher模板题)

hdu3068 maacher算法

HDU 3068 最长回文(Manacher)

HDU 3068 &&HDU 3294 +最长回文串*3—— manacher/扩展KMP/DP

HDU 3068 最长回文