Title: Algorithm (leetode, with mind mapping + all solutions) 300 questions (5) the longest back text substring

A Description of the topic

Overview of Two Solutions (Mind Mapping)

Three complete solutions

Scheme 1

1) code:

// Solution 1: sliding window method (" high time complexity, generally cannot pass ")
var longestPalindrome = function(s) {
    // Whether it is a palindrome string. (subStr = "for a little programming rigor")
    const isValid = (subStr = ' ') = > {
        const l = subStr.length;
        let resFlag = true;

        // Boundary: I < L /2
        for(let i = 0; i < l/2; i++) {
            // If the characters in "symmetric position" are not equal, then it must not be a palindrome
            if(subStr[i] ! == subStr[(l -1) - i]) {
                resFlag = false;
                break; }}return resFlag;
    }

    const l = s.length;
    // curMaxLength Specifies the maximum length of the current callback substring. The range is [l, 1].
    for (let curMaxLength = l; curMaxLength > 0; curMaxLength--) {
        // Under curMaxLength, the valid range of curStartIndex is [0, ((l + 1) - curMaxLength))
        for (let curStartIndex = 0; curStartIndex < ((l + 1) - curMaxLength); curStartIndex++) {
            const subStr = s.substr(curStartIndex, curMaxLength);
            // Once the palindrome is matched, the current substring must be the expected answer (" one ").
            // Because we curMaxLength is decreasing each time we iterate
            if (isValid(subStr)) {
                returnsubStr; }}}// <= s.length <= 1000; // <= 1;
    return "";
}
Copy the code

Scheme 2

1) code:

/ / the dynamic programming, plan 2 (s = = = s [j] [I] && dp + 1] [I] [j - 1) | | (s = = = s [j] [I] && (j + 1) - (I) < 3)
var longestPalindrome = function(s) {
    const l = s.length,
        S [I][j] indicates whether s[I, j] is a palindrome (double closed interval)
        // Initialize 1: dp with n*n values initialized to false
        dp = new Array(l).fill(false).map(item= > new Array(l).fill(false));
    // The starting substring and the maximum length of the current longest substring
    let maxStartIndex = 0.// Boundary: maxLength is initialized to 1. Otherwise there will be problems, can think by themselves ~
        maxLength = 1;

    // Initialize 2: dp is true on the diagonal
    for (let i = 0; i < l; i++) {
        for(let j = 0; j < l; j++) {
            if (i === j) {
                dp[i][j] = true; }}}// 2) State transition equation:
    // s[i][j] = (s[i] === s[j] && dp[i + 1][j - 1]) || (s[i] === s[j] && ((j + 1) - i) < 3)
    // s[I][j] = (1, 2, 3)
    // or (The first and last characters are the same && The interval between the first and last characters is < 3.) If the length of "bb" is less than 3, ensure that the first and last characters are the same
    for (let j = 1; j < l; j++) {
        for(let i = 0; i < j; i++) {
            if ((s[i] === s[j] && dp[i + 1][j - 1]) || (s[i] === s[j] && ((j + 1) - i) < 3)) {
                dp[i][j] = true;
                // If s[I, j] is a palindrome, we need to update maxStartIndex and maxLength
                // 3) Update the maxStartIndex and maxLength values when s[I, j] is a palindrome && (j + 1) -i) > maxLength
                if (((j + 1) - i) > maxLength) {
                    maxStartIndex = i;
                    maxLength = ((j + 1) - i); }}else {
                dp[i][j] = false; }}}MaxStartIndex; maxLength
    return s.substr(maxStartIndex, maxLength);
}
Copy the code

3 solution 3

1) code:

// Plan 3: The central diffusion method (note "both odd and even cases")
var longestPalindrome = function(s) {
    // Try to get a longer palindrome based on the substring passed in, left and right boundary subscripts
    const helper = (str, left, right) = > {
        while(left >=0 && right < l) {
            if (str[left] === str[right]) {
                // Check whether the maxStartIndex and maxLength values need to be updated
                if ((right + 1 - left) > maxLength) {
                    maxStartIndex = left;
                    maxLength = (right + 1 - left);
                }
                // Note: these two statements are placed at the end of the current if branch, not at the beginning!
                // Keep moving "outward" to try to get a longer palindrome string
                left--;
                right++;
            } else {
                // At this time STR [left]! == STR [right] == STR [right]
                break; }}}const l = s.length;
    // The starting index and maximum length of the current longest palindrome string.
    let maxStartIndex = 0,
        maxLength = 0;

    for (let i = 0 ; i < l; i++) {
        // 1) Odd: try to get a longer palindrome string by moving out with s[I]
        helper(s, i ,i);
        // 2) Even: try to get a longer palindrome string by moving out with s[I], s[I + 1]
        helper(s, i, i + 1);
    }
    
    return s.substr(maxStartIndex, maxLength);
}
Copy the code

4 scheme 4

1) code:

// Scheme 4 Manacher (" horse-drawn cart ") algorithm
class Solution {
    public String longestPalindrome(String s) {
        int start = 0, end = -1;
        StringBuffer t = new StringBuffer("#");
        for (int i = 0; i < s.length(); ++i) {
            t.append(s.charAt(i));
            t.append(The '#');
        }
        t.append(The '#');
        s = t.toString();

        List<Integer> arm_len = new ArrayList<Integer>();
        int right = -1, j = -1;
        for (int i = 0; i < s.length(); ++i) {
            int cur_arm_len;
            if (right >= i) {
                int i_sym = j * 2 - i;
                int min_arm_len = Math.min(arm_len.get(i_sym), right - i);
                cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len);
            } else {
                cur_arm_len = expand(s, i, i);
            }
            arm_len.add(cur_arm_len);
            if (i + cur_arm_len > right) {
                j = i;
                right = i + cur_arm_len;
            }
            if (cur_arm_len * 2 + 1 > end - start) {
                start = i - cur_arm_len;
                end = i + cur_arm_len;
            }
        }

        StringBuffer ans = new StringBuffer();
        for (int i = start; i <= end; ++i) {
            if(s.charAt(i) ! =The '#') { ans.append(s.charAt(i)); }}return ans.toString();
    }

    public int expand(String s, int left, int right) {
        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
            --left;
            ++right;
        }
        return (right - left - 2) / 2; }}Copy the code