• 【面试题】最长回文子串


    这个也算是很经典的题目了,O(n)的解法还是要自己钻进去想一想的,不能总以为自己会了,动手写一写才是王道。

    今天看了2013年9月15日北理工面试&算法讲座by_July&曹鹏的PPT,真是后悔当时没去听啊,已经不记得当时干什么去了,反正应该没有去听讲座有意义。。正题,然后又看到这个题,第N次看到了,却还没写过,实在不应该,今天就写了一下。话说,推荐 结构之法 算法之道 博客,博客置顶的博文里面可以找到PPT下载地址。

    题大家应该都知道,我就直接用PPT里面的了。

    例如ababcdedcbaab, 最长回文子串是abcdedcba。
    暴力解法1:
    枚举起点O(n)
    枚举终点O(n)
    判断回文O(n)
    总复杂度O(n^3)
    暴力解法2:
    枚举中间点O(n) (可能是两个字符之间,可能是1个字符)
    不断延伸判断回文O(n)
    总复杂度O(n^2)

    O(n)算法: Manacher
    奇数偶数统一处理,每个字符前后一个字符串中没出现的字符
    例如aba,变为了#a#b#a#,这样做的好处奇数、偶数统一处理。
    定义数组p[i],表示以i为中心[i – x ... i + x]是最长且回文的。
    还是上例:
    #a#b#a#
    0103010
    P[i]其实表示了原串中以该字符为中心的最长回文子串的长度(#表示原串中两个字符之间的位置为中心)。
    我们能否O(n)时间求出p数组?

    Manacher算法
    算p[i]时假设p[0 ... i – 1]已经计算好了,对前面的p[x],我们定义一个框[x – p[x] ... x + p[x]],定义right是max{x + p[x]}, center = argmax{x + p[x]},即right是之前所有框的最右边的位置,center是这个框的中心,框里的串是个回文子串。
    现在要计算p[i],我们算一下其关于center的对称点i’ = center * 2 – i,问题关键是回文串的对称性,从框左边left...i’和i...right是一致的,如果p[i’]的长度能把i + p[i’]限制在框里,则有p[i] = p[i’],因为框住的东西比较过了。

    如果框不住p[i’]的长度,导致其超出i + p[i’]右边界,就是框不住的东西,是需要比较的。

    p[i]至少等于min{p[i’], right – i}。
    继续暴力比较,更新right。
    为啥算法是O(n)的?因为right只能增加n次……

    code:

     1 int MaxHuiwen(string str)
     2 {
     3     if(str.empty())
     4         return 0;
     5     string strCharp = "#";
     6     for(int i = 0; i < str.length(); ++i)
     7     {
     8         strCharp += str[i];
     9         strCharp += "#";
    10     }
    11     int len = strCharp.length();
    12     int *p = new int[len];
    13     p[0] = 0;
    14     int l = 0, c = 0, r = 0, maxl = 1;
    15     for(int i = 1; i < len; ++i)
    16     {
    17         int j = (c << 1) - i;
    18         if(j >= 0 && i + p[j] < r)
    19             p[i] = p[j] < r - i ? p[j] : r - i;
    20         else
    21         {
    22             for(p[i] = 0; i-p[i]-1 >= 0 && i+p[i]+1 < len && strCharp[i+p[i]+1] == strCharp[i-p[i]-1]; ++p[i]);
    23             c = i;
    24             r = i+p[i];
    25             l = i-p[i];
    26         }
    27         maxl = maxl > p[i] ? maxl : p[i];
    28     }
    29     delete p;
    30     return maxl;
    31 }

    扩展(codility Gammar 2011)
    给定一个全部由字母组成的字符串,求这样的下标对数(x,y)满足x < y并且[x...y]的字符串是回文的。如果数量超过10^8,返回-1。
    p数组告诉我们什么?
    如果p[i] = 6表示,我们实际上有一个以i为中心长度为6的回文串,那么长度为4和2依然是回文的,实际上包含了3个回文串。
    如果p[i] = 5,实际上我们有3个长度分别为5,3,1的回文串。
    我们不要长度为1的,也就是说我们求的是所有p[i]/2的和。

  • 相关阅读:
    Elastic Search查询DSL的生成器
    清除Git仓库未托管的文件
    在Asp.net Core 中配置HTTPS支持
    VUE3的新构建工具Vite使用简介
    文档驱动 —— 表单组件(六):基于AntDV的Form表单的封装,目标还是不写代码
    文档驱动 —— 查询组件:使用 vue3.0 的新特性,重构代码
    文档驱动 —— 表单组件(五):基于Ant Design Vue 的表单控件的demo,再也不需要写代码了。
    文档驱动 —— 表单组件(四):基于Ant Design Vue封装一些表单域控件
    文档驱动 —— 表单组件(三):基于原生html的表单组件demo
    文档驱动 —— 表单组件(二):meta生成器,告别书写代码
  • 原文地址:https://www.cnblogs.com/shirley130912/p/3369203.html
Copyright © 2020-2023  润新知