Longest palindrome substring (Java version)

table of Contents

1, title

2, Example

3, solutions

3.0 brute force

3.1 Dynamic Programming

3.2 Center expansion algorithm

3.3 Manacher algorithm

4. Reference


1, title

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

2, Example

示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:
输入: "cbbd"
输出: "bb"

3, solutions

3.0 brute force

This should be when there is no other solution, you should think of: violence to solve, list all sub-strings, to determine whether a string is a palindrome, saving the longest palindrome string.

    public static String longestPalindrome(String s) {
        String ans = "";
        int max = 0;
        int len = s.length();
        for (int i = 0; i < len; i++) {
            for (int j = i + 1; j <= len; j++) {
                String tmp = s.substring(i, j);
                if (isPalindromic(tmp) && tmp.length() > max) {
                    ans = tmp;
                    max = j - i;
                }
            }
        }
        return ans;
    }

    private static boolean isPalindromic(String s) {
        int len = s.length();
        for (int i = 0; i < len / 2; i++) {
            if (s.charAt(i) != s.charAt(len - i - 1)) {
                return false;
            }
        }
        return true;
    }

Time complexity: two for loops to O (n²), for determining whether the loop inside palindromic O (n), so that the time complexity is O (n³).

Space complexity: O (1), constant variables.

3.1 Dynamic Programming

Violent solution time complexity is too high, we can consider, some violent solution to remove duplicate judge.

First define: string s to the subscript i of the string subscript j P (i, j), if the index i from s to string index j is palindromic sequence, then P (i, j) = true, otherwise P (i, j) = false. As shown below:

则 P(i, j) = (P(i + 1, j - 1) && s[i] == s[j])。

So if we want to know the case of P (i, j) does not need to call a function to determine palindromic strings, only need to know (i + 1, j-1) P can be the case, so that less time complexity the O (n). Therefore, we can use the method of dynamic programming, space for time, we have obtained the P (i, j) stored.

image.png

If s [i + 1, j-1] is a palindromic sequence, as long as s [i] == s [j], we can determine s [i, j] is a palindromic sequence.

note:

Seek length is 1 and a length of not formulated upper side when P (i, j) 2, as the experience we into the formula P [i] [j] in the i> where j, such as seeking P [1] [2], we need to know the P [1 + 1] [2-1] = P [2] [1], and P [2] [1] represents the S [2, 1] is not palindromic sequence, this is clearly wrong, so we need to judge alone.

Therefore, we first initialize the length of a palindromic sequence of P [i, j], using the equation so that the upper proposed P (i, j) = (P (i + 1, j-1) && S [i] == S [j]), then both sides of each outward extension of a character, a length of 3, 5, and all the odd-length on all seek out. Similarly, the length of palindromic sequence initialization 2 P [i, i + 1], using the formula, length of 4, all of even length 6 would all seek out.

    public static String longestPalindrome(String s) {
        int sLen = s.length();
        int maxLen = 0;
        String ans = "";
        boolean[][] P = new boolean[sLen][sLen];
        // 遍历所有长度
        for (int len = 1; len <= sLen; len++) {
            for (int start = 0; start < sLen; start++) {
                int end = start + len - 1;
                // 下标越界,结束循环
                if (end >=sLen) {
                    break;
                }
                P[start][end] = (len == 1 || len == 2 || P[start + 1][end - 1]) && s.charAt(start) == s.charAt(end);
                if (P[start][end] && len > maxLen) {
                    maxLen = len;
                    ans = s.substring(start, end + 1);
                }
            }
        }
        return ans;
    }

Time complexity: two cycles O (n²).

Space complexity: saving two-dimensional array with each sub-string PP case O (n²).

The following analysis of space usage :( to "babad" for example)

When we find the length of the case 5 of the sub-string, in fact only used the length of the case 4, and a length of 1 and 2 and the substring 3 where in fact no longer needed.

However, due to the cycle we are not done with the subscript P array, there is no method of optimizing think.

So we change the kinds of ideas, the same formula:

In fact, we can see from the recurrence formula, we first know i +1 will know i, so we only need to traverse backwards on the line.

    public static String longestPalindrome(String s) {
        int sLen = s.length();
        String ans = "";
        boolean[][] P = new boolean[sLen][sLen];

        for (int i = sLen - 1; i >= 0; i--) {
            for (int j = i; j < sLen; j++) {
                P[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i < 2 || P[i + 1][j - 1]);
                if (P[i][j] && j - i + 1 > ans.length()) {
                    ans = s.substring(i, j + 1);
                }
            }
        }
        return ans;
    }

Did not change the time complexity and space complexity and before, Can we look at optimizing space complexity.

When the i-th row seek when we only need the i + 1-line information, and if required j j-1 information, so as before j also need to reverse.

    public static String longestPalindrome(String s) {
        int sLen = s.length();
        String ans = "";
        boolean[] P = new boolean[sLen];

        for (int i = sLen - 1; i >= 0; i--) {
            for (int j = sLen - 1; j >= i; j--) {
                P[j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || P[j - 1]);
                if (P[j] && j - i + 1 > ans.length()) {
                    ans = s.substring(i, j + 1);
                }
            }
        }

        return ans;
    }

Time Complexity: constant O (n²).

Space complexity: reduced to O (n).

3.2 Center expansion algorithm

We know that certain palindromic sequence is symmetric, so we can select a center of each cycle, for about expansion, determines whether the character is equal to about.

image.png

Because the string of odd and even-numbered string exists, so we need to start from a extended characters, or between two characters from the beginning of the expansion, so a total of

n + (n-1) centers.

    public static String longestPalindrome(String s) {
        if (s == null || s.length() < 1) {
            return "";
        }
        int start = 0, end = 0;
        for (int i = 0; i < s.length(); i++) {
            int len1 = expandAroundCenter(s, i, i);
            int len2 = expandAroundCenter(s, i, i+1);

            int len = Math.max(len1, len2);
            if (len > end - start) {
                start = i - (len-1) / 2;
                end = i + len / 2;
            }
        }

        return s.substring(start, end + 1);
    }

    public static  int expandAroundCenter(String s, int left, int right) {
        int L = left, R = right;
        while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
            L--;
            R++;
        }
        return (R-1) - (L+1) + 1;
    }

3.3 Manacher algorithm

https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html

4. Reference

https://leetcode-cn.com/problems/longest-palindromic-substring/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-bao-gu/

https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html

Published 95 original articles · won praise 16 · views 50000 +

Guess you like

Origin blog.csdn.net/tiankong_12345/article/details/102018257