zoukankan      html  css  js  c++  java
  • Manacher算法

    给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.

    摘自:

    http://blog.csdn.net/dyx404514/article/details/42061017

    先说一个O(n^2)复杂度解法:
    根据长度奇偶性,找对称轴,奇数长度取节点,偶数取节点空隙,然后往左右两边延展匹配

    Manacher算法:线性复杂度

    1.为了不分奇偶两种情况,直接预处理将相邻节点间插一个"#"


    2.存一个len[i](记录对称轴为i的向右最大长度),那么最后要求的实际回文串长度为len[i]-1


    3.记忆化更新。设已处理完0 ~ i-1位置,前i个位置得出的最长回文串最右端边界位置为P,对称轴为P0。 且我们可以找到 i 关于P0 的对称点j (j<i , len[j]已知)
    那么对于对称轴在i位置,分三种情况:

    1. i<=P 且 i+len[j]-1<=P => len[i]=len[j]

     

    2. i<=P 且 i+len[j]-1>P => len[i]=len[j]+超出部分(手动匹配)


    3. i>P => 完全手动匹配

     


    上代码:

    char str[N]; //原数组
    char temp[N];//#转换后数组
    int len[N];
    
    //转换原始串
    int init(char *s){
    int len=strlen(s);
    temp[0]='@';//防止越界
    for(int i=1;i<=len*2;i+=2){
    temp[i]='#';
    temp[i+1]=s[i/2];
    }
    temp[2*len+1]='#';
    temp[2*len+2]='@';//防越界
    return 2*len+1;//返回转换长度
    }
    
    int manacher(char *s,int len){ //temp,2*len+1
    int mx=0;//当前最大回文串右端边界位置
    int ans=0,p0=0;
    For(i,1,len){
    int j=2*p0-i; //j关于i的对称点
    if(i>mx)len[i]=1;
    else len[i]=min(len[j],mx-i);
    while(temp[i-len[i]]==temp[i+len[i]])len[i]++;
    if(len[i]+i-1>=mx){ //记得实时更新p0,mx
    mx=len[i]+i-1;
    p0=i;
    }
    chkmax(ans,len[i]-1);
    }
    return ans;
    }
    
     
  • 相关阅读:
    DB2创建序列
    hibernate注解影射表
    自定义异常类一
    【JVM】java方法区
    【JVM】java棧
    (2)java堆内存
    (1)java虚拟机概念和结构图
    枚举应用五
    设计模式之命令模式学习理解
    eclipse中javadoc给项目生成api文档
  • 原文地址:https://www.cnblogs.com/planche/p/9387947.html
Copyright © 2011-2022 走看看