zoukankan      html  css  js  c++  java
  • 【算法】最长回文子串 longest palindrome substring

    对于字符串S, 要找到它最长的回文子串,能想到的最暴力方法,应该是对于每个元素i-th都向左向右对称搜索,最后用一个数组span 记录下相对应元素i-th为中心的回文子串长度。

    那么问题来了:

      1. 这样的方法,对于奇回文子串和偶回文子串的处理不一样,比如所“acbca” 和“acbbca”

      2. 计算冗余,e.g. ”sscssabcccchccccba“中, 自左向右遍历计算的话,会发现, ”abcccchccccba“是对称的,而这个回文字符串里又左右对称分别包含了两个回文子字符”cccc“和”cccc“, 在对第二个”cccc“字符串遍历的时候,其实可以利用到”abcccchccccba“的对称性来直接赋值,而不用再次计算

    于是,引出了Manacher's 算法:

      1. 为了可以对奇偶回文字符串不加区分地处理,对输入字符串增加边界元素(输入字符串S长度为N -> S2长度为2*N+1):e.g. ”aabbbcc“ -> "#a#a#b#b#b#c#c#" , ”aabbcc“ -> "#a#a#b#b#c#c#"

      2. 对于S2字符串,自左向右,每个字符逐个计算和处理

        1)用span[maxInputStringLength*2+1]数组来记录每个元素i-th为中心的回文字符串长度 : 初始化 span[0] = 0

        2)用center 和 rightBoundary 来记录上一个已知的回文字符串中心index和最右边界index :初始化 center = 0, rightBoundary = 0

        3)用 i 表示当前处理的元素, i2 表示 以 center 为中心的 center左侧 i 对称 元素下标 : i2 = center - (i - center)= center * 2 - i

        4)加上已知的回文子串信息之后,假设已经处理了S2[0, i-1]范围的元素,那么已知的回文子串中心center 必然属于[0, i-1]区间, 但是对于rightBoundary和i的关系可以有三种情况:

          a)当前处理的元素(index = i)以 center为中心,对称的元素(index = i2)上有,span[i2] < rightBoundary - i - 1, 表示i2点的回文字符串最左端不会超过leftBoundary的长度,利用了已知的回文字符串信息辅助说明,当前以i为中心的回文字符串将和i2完全对称,span[i] = span[i2]

          

          b)当前处理的元素(index = i)以 center为中心,对称的元素(index = i2)上有,span[i2] >= rightBoundary - i - 1, 表示 i2 点的回文字符串最左端已经超过了leftBoundary的范围,不能利用已知回文字符串直接赋值,但还是可以利用对称性,使得对称搜索从rightBoundary处开始,这样可以减少计算

          

          c)当前处理的元素(index = i)并不在已知回文串的记录范文内,那么久没有辅助信息,需要从i元素的左右对称搜索,得到span[i]的值

          

        5)最后要更新center和rightBoundary的值,使得已知回文字符串的覆盖范围右移,这样可以持续辅助搜索

      

     1 const int maxStringLength = 1000;
     2 
     3 string longestPalindrome(string s) {
     4 
     5     if (s.empty()) return "";
     6 
     7     ///add boundary
     8     string s2;
     9     for (int i = 0; i < s.size(); i++) {
    10         s2.push_back('#');
    11         s2.push_back(s[i]);
    12     }
    13     s2.push_back('#');
    14 
    15 
    16     /// setting
    17     int span[maxStringLength] = {0};
    18     span[0] = 0; // init the first element's length of palindrome
    19     int center = 0, rightBoundary = 0;
    20     int left = 0, right = 0;
    21 
    22     ///traverse 
    23     for (int i = 1; i < s2.size(); i++) {
    24         if (i <= rightBoundary) {
    25             int i2 = center * 2 - i;// center - (i - center)
    26             if (span[i2] < (rightBoundary - i - 1)) {
    27                 span[i] = span[i2];
    28                 left = -1;
    29             }
    30             else {
    31                 span[i] = rightBoundary - i;
    32                 right = rightBoundary + 1;
    33                 left = i * 2 - right; //i - (right - i)
    34             }
    35         }
    36         else {
    37             span[i] = 0;
    38             left = i - 1;
    39             right = i + 1;
    40         }
    41 
    42         while (left >= 0 && right < s2.size() && s2[left] == s2[right]) {
    43             span[i] ++;
    44             left--;
    45             right++;
    46         }
    47 
    48         if ((i + span[i]) > rightBoundary) {
    49             center = i;
    50             rightBoundary = i + span[i];
    51         }
    52     }
    53 
    54     /// find the max span length
    55     int maxSubstringCenter = 0, maxSubstringLen = 0;
    56     for (int i = 0; i < s2.size(); i++) {
    57         if (span[i] > maxSubstringLen) {
    58             maxSubstringLen = span[i];
    59             maxSubstringCenter = i;
    60         }
    61     }
    62 
    63     /// remove boundary '#' from substring
    64     string result;
    65     for (int i = maxSubstringCenter - maxSubstringLen; i <= maxSubstringCenter + maxSubstringLen; i++) {
    66         if (s2[i] != '#')
    67             result.push_back(s2[i]);
    68     }
    69 
    70     return result;
    71 }
    View Code
  • 相关阅读:
    AtCoder Beginner Contest 167
    AtCoder Beginner Contest 166
    AtCoder Beginner Contest 165
    AtCoder Beginner Contest 164
    AtCoder Beginner Contest 163
    AtCoder Beginner Contest 162
    AtCoder Beginner Contest 161
    AtCoder Beginner Contest 160
    AtCoder Beginner Contest 159
    自定义Mybatis自动生成代码规则
  • 原文地址:https://www.cnblogs.com/cheermyang/p/6674784.html
Copyright © 2011-2022 走看看