Palindromic longest substring (dynamic compliance, the center of diffusion, Manacher algorithm)

topic

leetcode:5. Longest Palindromic Substring

solution

Dynamic Programming

Time complexity \ (O (n ^ 2) \) , the space complexity \ (O (n ^ 2)
\) substantially directly look at the code Solution

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n, true));
        int rx, ry;
        
        rx = ry = 0;
        for(int l = 1; l < n; l++){
            for(int i = 0; i < n - l; i++){
                int j = i + l;
                if(s[i] == s[j] && (j - i < 3 || dp[i+1][j-1])){
                    dp[i][j] = true;
                    if(j - i > ry - rx){
                        ry = j;
                        rx = i;
                    }
                } else {
                    dp[i][j] = false;
                }
            }
        }
        
        return s.substr(rx, ry - rx + 1);
    }
};

Center diffusion method

Time complexity \ (O (^ n-2) \) , the space complexity \ (O (1) \)
Let's assume that a point spread to the ends to the center, to find the center point of the longest substring palindromic

class Solution {
public:
    
    int rx, ry;
    void helper(string &s, int i, int offset){
        int left = i;
        int right = i + offset;
        while(left >= 0 && right < s.size() && s[left] == s[right]){
            left--;
            right++;
        }
        
        if(right - 1 - (left + 1) > ry - rx){
            ry = right - 1;
            rx = left + 1;
        } 
    }
    string longestPalindrome(string s) {
        int n = s.size();
    
        rx = ry = 0;
       
        for(int i = 0; i < n; i++){
            helper(s, i, 0);
            helper(s, i, 1);
        }
        
        return s.substr(rx, ry - rx + 1);
    }
};

Manacher algorithm

Manacher algorithm known as "algorithm on horse", time complexity \ (O (n-) \) , the spatial complexity (O (n) \) \
as palindromic strings strings is odd and has a length of even length, in order to handle both cases, may be inserted into a special character '#' in the string, so that the whole length of the new string length becomes an odd number, such as "aa" becomes "# a # a #", then the string can be header added another special character '$' and the tail of the '@', so you do not have special handling cross-border issues (unified border processing)
to "122,112,321" for example after the previous step to "@ # 1 # 2 # 1 # 2 # 2 # # #. 3. 1 # 2 #. 1 "
Manacher algorithm uses an auxiliary array r [i] expressed as t [i] as the center of the rightmost character of the longest substring palindromic t [i] of length, such as the t [i] as the center of the longest substring palindromic t [low, high], then r [i] = high - i + 1, t [low, high] = 2 * r [i] -1, len array has a nature, that r [i] -1 for palindromic substring in the original string length, proved to be very simple t [lowl, high] sure is "#" at the beginning and end, so that the inserted "#" is the original string more than twice that of a character, so that the original string to the longest length of palindromic sequence r [i] - 1, so that the problem of the longest seek into r [i]

Len array of computing

The main advantage of the existing algorithm palindromic substring characteristics, reducing the search time, from left to right is calculated len [i], calculates a center position while preserving the right end of the longest substring before palindromic maximum value and the corresponding R c,

  • i <R, first find the symmetry point c i A j = 2 * ci, then at least R & lt [i] \ (\ GEQ \) min (R & lt -. 1 + i, P [J]), and then manually match exceeds section
  • i> = R, then can not use future knowledge of any assumption, it can only be assumed to be at least 1, and then manually match
class Solution {
public:
  
    string longestPalindrome(string s) {
        int n = s.size();
        if(n == 0) return "";
        string ns;
        ns.push_back('$');
        for(int i = 0; i < n; i++){
            ns.push_back('#');
            ns.push_back(s[i]);
        }
        ns.push_back('#');
        ns.push_back('@');
        n = ns.size();
        vector<int> r(n);
        int c, R, C, MAX;
        R = -1;
        MAX = 0;
        C = 0;
        for(int i = 1; i < n; i++){
            r[i] = i < R ? min(r[2 * c - i], R - i + 1) : 1;
            while(ns[i + r[i]] == ns[i - r[i]]) r[i]++;
            r[i]--;
            if(i + r[i] > R){
                R = i + r[i];
                c = i;
            }
            if(r[i] > MAX){
                MAX = r[i];
                C = i;
            }
           
        }
        
        return s.substr((C-MAX)/2, r[C]);
    }
};
Time complexity analysis

reference

Guess you like

Origin www.cnblogs.com/qbits/p/11229279.html