• 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
    ",manacher(len));
        getchar();
      }
    }
    View Code
  • 相关阅读:
    bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序【置换群】
    【20】AngularJS 参考手册
    【19】AngularJS 应用
    【18】AngularJS 包含
    【17】AngularJS Bootstrap
    【16】AngularJS API
    【15】AngularJS 输入验证
    【14】AngularJS 表单
    【13】AngularJS 模块
    【12】AngularJS 事件
  • 原文地址:https://www.cnblogs.com/zhgyki/p/9026730.html
Copyright © 2020-2023  润新知