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;
    }
    
     
  • 相关阅读:
    浅析c#中new、override、virtual关键字的区别
    数据解析1113
    Silverlight中xaml之间的跳转方案之一
    silverlight读取client文件的完整路径
    (Transfered)WPF Tutorial:Beginning
    数据解析1112
    邮件发送1
    TortoiseSVN Settings Subversion
    德信无线10Q4净利润同比增进187%
    欧盟中止对我数据卡双反调查
  • 原文地址:https://www.cnblogs.com/planche/p/9387947.html
Copyright © 2011-2022 走看看