The longest palindrome substring of LeetCode question 5

Given a string  s , find   the longest palindrome substring in s . You can assume that  has a maximum length of 1000.

Example 1:

Input: "babad"
 Output: "bab"
 Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
 Output: "bb"
Idea 1: Violent search.

Idea 2: Center expansion method.

Idea 3: Dynamic Programming

Find longest palindrome string
Using dynamic programming to find the longest palindrome string often relies on a two-dimensional Boolean array, as shown in the figure:
Java string - dynamic programming to find the longest palindrome string
Each dp[i][j] represents a square in the figure, and T and F in each square represent whether the current substring is a palindrome, such as
dp[1][4]="baab", by definition, can completely determine the value of the square in the upper triangle of the figure in the initial state.
Going back to the palindrome string, such as "balalab", the principle of determination is that str[0] is equal to str[6] and "alala" is a palindrome string. Converted to a mathematical expression, str[i] == str [j] && dp[i+1][j-1] .
In this way, we can determine all palindrome strings and find the longest palindrome string.

Idea 4: Manacher Algorithm

First of all, the Manacher algorithm can find the longest palindrome substring in O(n) time complexity.

(1). Overview of the Manager algorithm

  The Manacher algorithm can only solve strings of odd lengths, so the Manacher algorithm uses a more ingenious method to solve strings of odd or even lengths at the same time. The Manacher algorithm is implemented by converting strings, for example: the original string: abc, after conversion to get: #a#b#c#, so the original string length is odd or even, the final conversion can get a length of odd-numbered string.
  Secondly, the Manacher algorithm usually requires an array (we assume, the len array) to record the maximum length of the palindrome string of each character in the original string, in fact, the character obtained in the original string Half the length of the longest palindrome string.
  For example: aba, after conversion: #a#b#a#, the longest palindrome string that can be obtained by b is: #a#b#a#, we assume that the subscript of b is i, the longest string obtained is The subscript of the first character is left, the subscript of the last character is right, then the value corresponding to b is: right - i + 1;
  at the same time, we can also know that the maximum palindrome substring length obtained by the character corresponding to i Is: len[i] - 1, for example: in the above example, the subscript of b is 3, so len[3] = 4, then the palindrome string aba corresponding to b is exactly len[3] - 1 = 3. Why is this? We assume that the original string is oldString (unconverted), the converted string is newString, and if the length of oldString is length, then the length of newString is 2 * length + 1, so the length of the obtained string must be odd. . For the palindrome string corresponding to the i-th character in newString, the length must be 2 * len[i] - 1 (you can simply test this with an example), and at the same time, after observation, 2 * len[ i] - 1 character, len[i] must be #, the rest are normal symbols, because the number of # in all palindrome strings is always different from the number of other symbols by 1 .

(2). Calculation of len array

  First, we compute len[i] from left to right. When we compute len[i], len[j] has already been computed (0 < j < i).
  We assume that the maximum value of the right end point of the longest palindrome substring is obtained among the calculated characters (the palindrome string is not necessarily the longest palindrome string, but the subscript on the right end of the palindrome string is required to be the largest ), assuming that the maximum value is rightIndex, and the position of the center of the palindrome substring is set to centerIndex, then there are two cases:

  A.i < rightIndex

  We assume that centerIndex is the center, and i corresponds to j. As shown in the figure:



  What we know is that with centerIndex as the center, the palindrome string can reach rightIndex, then there are two cases:
  if i + len[j] < P, that is, the palindrome character centered on j The string is inside the palindrome string centered on centerInde. At this time, it can be obtained that the palindrome string centered on j is the same as the palindrome string centered on i. Why? Because they are inside the palindrome string centered at centerIndex. So what you can get is, len[i] = len[j].
  If i + len[j] >= P, that is to say, a part of the palindrome string centered on i is outside the palindrome string centered on centerIndex. At this time, the external part requires us to write one by one. calculate.

  B.i > rightIndex

  If i > rightIndex, it means that the palindrome string centered on i does not match at all. So we need to match one by one.

Code:
public class LongestPalindrome {

	private static int max = 0;
	private static String res = "";

	public static String longestPalindrome1(String s) {
		for (int size = s.length(); size > 0; size--) {
			for (int low = 0, high = low + size - 1; high < s.length(); low++, high++) {
				if (shrinkCheckPalindrome(s, low, high)) {
					return s.substring(low, high + 1);
				}
			}
		}
		return s.substring(0, 1);
	}

	public static boolean shrinkCheckPalindrome(String s, int low, int high) {
		while (low <= high) {
			if (s.charAt(low) == s.charAt(high)) {
				low++;
				high--;
			} else {
				return false;
			}
		}
		return true;
	}

	public static String longestPalindrome2(String s) {

		if (s.length() == 1) {
			return s;
		}
		for (int i = 0; i < s.length() - 1; i++) {
			checkPalindrome(s, i, i);
			checkPalindrome(s, i, i + 1);
		}
		return res;
	}

	public static void checkPalindrome(String s, int low, int high) {
		while (low >= 0 && high < s.length()) {
			if (s.charAt(low) == s.charAt(high)) {
				if (high - low + 1 > max) {
					max = high - low + 1;
					res = s.substring(low, high + 1);
				}
				low--;
				high++;
			} else {
				return;
			}
		}
	}

	public static String longestPalindrome3(String s) {
		int len = s.length();
		if (s == null || len == 0) {
			return s;
		}
		String res = "";
		int max = 0;
		// 创建一个行列均为字符串长度的二维数组,创建时默认初始化为false
		boolean[][] dp = new boolean[len][len];
		for (int j = 0; j < len; j++) {
			for (int i = 0; i <= j; i++) {
				// 这里只考虑了i<=j的情况,因为i>j时均为false
				// 当i==j,j-i==1,j-i==2时,只要满足s.charAt(i) == s.charAt(j)就是回文字符串
				// 如果不是这样,还要判断当前回文字符串的子串是不是回文字符串,即dp[i + 1][j - 1]),这就是动
				// 态规划思想
				dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1][j - 1]);
				if (dp[i][j]) {// 如果是回文字符串
					if (j - i + 1 > max) {// 并且比之前的回文字符串要长,更新字符串长度,记录字符串
						max = j - i + 1;
						res = s.substring(i, j + 1);
					}
				}
			}
		}
		return res;
	}

	public static String longestPalindrome4(String s) {
		// -----------------------------------
		// 转换字符串
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("#");
		for (int i = 0; i < s.length(); i++) {
			stringBuilder.append(s.charAt(i));
			stringBuilder.append("#");
		}
		// -----------------------------------
		int rightIndex = 0;
		int centerIndex = 0;
		// 求len中的最大
		int answer = 0;
		// answer最大时的中心
		int index = 0;
		int len[] = new int[stringBuilder.length()];
		for (int i = 1; i < stringBuilder.length(); i++) {
			// 当rightIndex > i,那么我们就在rightIndex - i 与len[2 * centerIndex - i](len[j]),取得最小值
			// 因为当i + len[j] < rightIndex时,我们就把len[i]更新为len[j]
			// 但是如果i + len[j] >= rightIndex时,我们暂且将len[i]定更新为rightIndex - i,超出的部分需要我们一个一个的匹配
			if (rightIndex > i) {
				len[i] = Math.min(rightIndex - i, len[2 * centerIndex - i]);
			} else {
				len[i] = 1;
			}
			// 一个一个匹配
			// 要么是超出的部分,要么是i > rightIndex
			while (i - len[i] >= 0 && i + len[i] < stringBuilder.length()
					&& stringBuilder.charAt(i - len[i]) == stringBuilder.charAt(i + len[i])) {
				len[i]++;
			}
			// 当 len[i] + i > rightIndex,我们需要更新centerIndex和rightIndex
			// 至于为什么会这样做,理解一下rightIndex和centerIndex的含义
			if (len[i] + i > rightIndex) {
				rightIndex = len[i] + i;
				centerIndex = i;
			}
			if (len[i] > answer) {
				answer = len[i];
				index = i;
			}
		}
		// 截取字符串
		// 为什么index - answer + 1,因为len[i] - 1才是原来的回文字符串长度,而answer记录的是len中最大值
		return stringBuilder.substring(index - answer + 1, index + answer).replace("#", "");

	}

	public static void main(String[] args) {
		String s = "abcdad";
		System.out.println(longestPalindrome4(s));
	}
GitHub address: https://github.com/xckNull/Algorithms-introduction

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324848699&siteId=291194637