zoukankan      html  css  js  c++  java
  • 【Manacher(马拉车)算法】

    Manacher

    英译过来就是马拉车

    是一个求一个字符串中最长回文连续子序列的算法

    例如abaabaabb最长的就是7

    abaaaaba最长就是8

    ababbb最长就是3

    注意:一个字符串可能不只有一个最长回文连续子序列

    传统做法就是枚举中间点向两边扩展,时间复杂度是O(N^2)

    然后这个算法就优化到了O(N)

    这是优化吗,性质都变了啊喂

    算法实现

    首先回文分为两种:奇回文偶回文如果枚举的话,有时候是字符,有时候要枚举字符之间的位置,就很麻烦

    为了操作方便(因为我们要定义以i为中心),我们把它们都变成奇回文

    怎么做呢?很简单,全部插入一个符号即可(没出现过)

    例如  

    abaababa ——> (#a#b#a#a#b#a#b#a#)

    前后是防止越界,你可以随便定义(只要字符串里没有的,不会冲突)

    原来aba就可以变成#a#b#a#

    原来baab就可以变成#b#a#a#b#

    这样一来就全部变成了奇回文啦!

    我们定义P[i]是以i为中心的,最长回文串的半径(包括自己)

    字符串 ( # a # b # a # a # b # a # b # a # )
    P 1 1 2 1 4 1 2 7 2 1 4 1 2 1 4 1 2 1 1

    我们现在要做的就是O(N)处理出每一个P[i]

    考虑能不能根据之前已经得到的来推测出答案呢

     当前我们枚举到i,已知有一个以mid为中心的回文子串,其右端点到了mx

    可知以mid为分界线,左右两边是完全对称的(回文子串定义)

    当i+p[j]<mx时

     我们就可以直接更新答案,因为不可能更长了

    当i+p[j]>=mx时

    我们只能到mx这个位置,因为我们不知道mx后面是否还能继续匹配

     (只取红色部分)

    我们就可以根据i的对称点j来更新答案,但是p[i]不一定等于p[j],因为mx后面的还是未知的,我们不知道,这一部分暴力匹配就是了

    可知mx是一直在增大,每增大一次,我们需要比较一次,mx最多从0到n,所以也就是O(N)的复杂度

    其实和KMP都有一个运用已知答案的思想

    最后输出答案的时候我们半径减一即可(可以自己手%一下找找规律)

    【模板】manacher算法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 char s_new[21000002];
     4 char s[11000002];
     5 int p[21000002];
     6 int INIT(){//转换字符串 
     7     int len=strlen(s);
     8     s_new[0]='$';
     9     s_new[1]='#';
    10     int j=2;
    11     for(int i=0;i<len;i++)
    12     {
    13         s_new[j++]=s[i];
    14         s_new[j++]='#';
    15     }
    16     s_new[j]='';
    17     return j;
    18 }
    19 int manacher()
    20 {
    21     int len=INIT();
    22     int ans=-1;
    23     int id;//中心 
    24     int mx=0;//能达到的已知的右端点 
    25     for(int i=1;i<=len;i++)
    26     {
    27         if(i<mx)
    28             p[i]=min(p[2*id-i],mx-i);//更新取较小的一个 
    29         while(s_new[i+p[i]]==s_new[i-p[i]])//暴力扩展 
    30             p[i]++;
    31         if(mx<i+p[i])//更新mx 
    32         {
    33             id=i,
    34             mx=p[i]+i;
    35         }
    36         ans=max(ans,p[i]-1);//更新答案 
    37 
    38     }
    39     return ans;
    40 }
    41 int main()
    42 {
    43     scanf("%s",s);
    44     cout<<manacher();
    45     return 0;
    46 }
  • 相关阅读:
    基于opencv网络摄像头在ubuntu下的视频获取
    VHDL学习札记:library and Package
    HLS入门收集(1)
    Windows下zlib库和libPng库的编译和使用
    FPGA培训体会 江苏大学 自动化 许一航
    FPGA学习体会
    FPGA培训体会
    2016年上海V3学院寒假班FPGA/SOC培训收获
    上海V3学院FPGA培训感想 ——重庆理工大学叶钧
    上海招聘FPGA讲师(专兼职均可)
  • 原文地址:https://www.cnblogs.com/hualian/p/13801067.html
Copyright © 2011-2022 走看看