美文网首页
Algorithm - Longest Palindromic

Algorithm - Longest Palindromic

作者: cctoken | 来源:发表于2019-03-31 14:38 被阅读0次

Algorithm LongestPalindromic SubString

Description

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"

Output: "bb"

Submission

class Solution {
    public String longestPalindrome(String s) {
            if (s.length() <= 1) {
      return s;
    }
    StringBuffer stringBuffer = new StringBuffer();

    for (int i = 0; i < s.length(); ++i) {
      stringBuffer.append("#");
      stringBuffer.append(s.charAt(i));
    }
    stringBuffer.append("#");

    int length = stringBuffer.length();

    int[] posVal = new int[length];

    int maxLength = 0;
    int rMax = 0;
    int maxCenter = -1;
    int validPos = -1;

    for (int i = 0; i < length; ++i) {
      if (i == 0) {
        posVal[i] = 0;
        maxCenter = i;
        rMax = 0;
        validPos = 0;
      } else {
        int left;
        int right;
        if (rMax > i) {
          int opPos = 2 * maxCenter - i;
          int leastLen = posVal[opPos];
          leastLen = Math.min(leastLen, rMax - i);
          left = i - leastLen;
          right = i + leastLen;
          while(left >= 0 && right < length && stringBuffer.charAt(left) == stringBuffer.charAt(right)) {
            left --;
            right ++;
          }

        } else {
          left = i - 1;
          right = i + 1;
          while(left >= 0 && right < length && stringBuffer.charAt(left) == stringBuffer.charAt(right)) {
            left --;
            right ++;
          }

        }
        if (right - 1 > rMax) {
          rMax = right - 1;
          maxCenter = i;
        }
        posVal[i] = right - 1 - i;

      }


      if (posVal[i] > maxLength) {
        maxLength = posVal[i];
        validPos = i;
      }

    }

    StringBuffer res = new StringBuffer();
    for (int k = validPos - maxLength; k <= validPos + maxLength; ++k) {
      if ((k & 1) == 1) {
        res.append(stringBuffer.charAt(k));
      }
    }
    return res.toString();
    }
}

Solution

获取最长回文子串,上面代码的实现是基于Manacher's algorithm.

在讲解这个算法之前,我们先讲述一个简单的实现方式,只是在时间复杂度上较高达到了O(N²)

针对字符串

"acdeedcb"

我们可以知道最长回文子串是 "cdeedc"

首先我们在字符串的每个字符之间插入一个额外字符 '#',便形成了"#c#d#e#e#d#c",这个时候我们依次遍历该字符串的每个字符,
从左往右。

当遍历到位置 i时,分别比较left和right对应的字符是否相同,如果相同则继续向两侧扩张比对,直至不同或到边界的地方停止,记录此时仍满足字符相等的位置,因而可以计算出以i为中心的最长回文子串。当整个字符串都被遍历完之后
便可以得到所有位置的最长回文子串,得到最终结果。

Manacher 算法 的思路是基于上面遍历算法的基础之上的,利用已遍历过位置的对称信息,在此基础之上降低了时间复杂度。

我们假设从左至右依次遍历,位置为i,记录访问过的所有位置的回文子串所能到达的最右边界,记为rMax,同时记录该边界对应的中心 maxCenter

那么我们必然能够利用到一点信息,即当前访问的位置 i必然在之前已经标记到的位置 maxCenter 的右侧,这个时候会引入两种情况,

i在rMax的左侧,那么i在(2maxCenter-rMax,rMax)区间内的对称性必然是一致的,也就是说 posVal[i] = Math.min(pos[2maxCenter-i], rMax-i),其中posVal数组记录每个位置的回文子串右边界至当前位置的距离,也对应着回文子串的长度。

我们能够在i位置直接得到当前位置回文子串的最小长度,以此为边界向两侧扩张,可以得到具体的i位置的回文子串的长度。

Runtime: 10 ms, faster than 79.83% of Java online submissions for Longest Palindromic Substring.

Memory Usage: 39.6 MB, less than 18.89% of Java online submissions for Longest Palindromic Substring.

相关文章

网友评论

      本文标题:Algorithm - Longest Palindromic

      本文链接:https://www.haomeiwen.com/subject/lwzybqtx.html