5.Longest Palindromic Substring (String; DP)

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

思路:KMP,一种字符串匹配方法。

首先在字符串的每个字符间加上#号。For example: S = “abaaba”, T = “#a#b#a#a#b#a#”。这样所有的回文数都是奇数,以便通过i的对应位置i’或者p[i]
P[i]存储以i为中心的最长回文的长度。For example: 
T = # a # b # a # a # b # a #
P = 0 1 0 3 0 1 6 1 0 3 0 1 0
下面我们说明如何计算P[i]。
假设我们已经处理了C位置(中心位置),它的最长回文数是abcbabcba,L指向它左侧位置,R指向它右侧位置。
现在我们要处理i位置。
if P[ i' ] ≤ R – i,
then P[ i ] ← P[ i' ]
else P[ i ] ≥ P[ i' ]. (Which we have to expand past the right edge (R) to find P[ i ].
If the palindrome centered at i does expand past R, we update C to i, (the center of this new palindrome), and extend R to the new palindrome’s right edge.
 
时间复杂度分析:
In each step, there are two possibilities. 
  • If P[ i ] ≤ R – i, we set P[ i ] to P[ i' ] which takes exactly one step. 
  • Otherwise we attempt to change the palindrome’s center to i by expanding it starting at the right edge, R. Extending R (the inner while loop) takes at most a total of N steps, and positioning and testing each centers take a total of N steps too. Therefore, this algorithm guarantees to finish in at most 2*N steps, giving a linear time solution.

那么总共时间复杂度最坏是O(n2),最好是O(n)

class Solution {

public:

  string preProcess(string s) {

    int n = s.length();

    if (n == 0) return "^$";

    string ret = "^";

    for (int i = 0; i < n; i++)

      ret += "#" + s.substr(i, 1);

 

    ret += "#$";

    return ret;

  }

 

  string longestPalindrome(string s) {

    string T = preProcess(s);

    int n = T.length();

    int *P = new int[n];

    int C = 0, R = 0;

    for (int i = 1; i < n-1; i++) {

      int i_mirror = 2*C-i; // equals to i_mirror = C - (i-C)

    

      //if p[i_mirror] < R-i: set p[i] to p[i_mirror]

      P[i] = (R > i) ? min(R-i, P[i_mirror]) : 0;

    

      //else: Attempt to expand palindrome centered at i

      while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) //因为有哨兵^$所以不用担心越界

        P[i]++;

      

      //if the palindrome centered at i does expand past R

      if (i + P[i] > R) {

        C = i;

        R = i + P[i];

      }

    }

 

    // Find the maximum element in P.

    int maxLen = 0;

    int centerIndex = 0;

    for (int i = 1; i < n-1; i++) {

      if (P[i] > maxLen) {

        maxLen = P[i];

        centerIndex = i;

      }

    }

    delete[] P;

  

    return s.substr((centerIndex - 1 - maxLen)/2, maxLen);

  }

};

 

你可能感兴趣的:(substring)