Longest Palindromic Substring

问题描述

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.

 

解决思路

1. 动态规划:时间空间复杂度均为O(n^2);

2. 中心扩展法:注意考虑奇数长度和偶数长度的情况,时间复杂度为O(n^2);

3. Manacher算法:

(1) 用#夹杂在字符串中,进行填充,首字符为$;

(2) 动态规划求解,记录最长回文子串的长度和中心位置;

(3) 去除多余的字符;

时间空间复杂度均为O(n).

 

程序

// dp
public class Solution {
    public String longestPalindrome(String s) {
		if (s == null || s.length() == 0) {
			return "";
		}
		int n = s.length();
		int begin = 0, maxLen = 1;
		boolean[][] isPalindrome = new boolean[n][n];
		// 初始化
		// 单个字符为回文串
		for (int i = 0; i < n; i++) {
			isPalindrome[i][i] = true;
		}
		// 连续两个相同的字符也是回文串
		for (int i = 0; i < n - 1; i++) {
			if (s.charAt(i) == s.charAt(i + 1)) {
				isPalindrome[i][i + 1] = true;
				begin = i;
				maxLen = 2;
			}
		}
		for (int i = n -3; i >= 0; i--) {
			for (int j = i + 2; j < n; j++) {
				if (s.charAt(i) == s.charAt(j) 
					&& isPalindrome[i + 1][j - 1]) {
					isPalindrome[i][j] = true;
					if (j - i + 1 > maxLen) {
						maxLen = j - i + 1;
						begin = i;
					}
				}
			}
		}
		return s.substring(begin, begin + maxLen);
	}
}

  

public class LongestPalindromicSubstring {
	// 中心匹配法, O(n^2), O(1)
	public String longestPalindrome(String s) {
		if (s == null || s.length() == 0) {
			return "";
		}

		int len = s.length();
		String res = "";

		for (int i = 0; i < len; i++) {
			String s1 = longestPString(s, i, i);
			String s2 = longestPString(s, i, i + 1);
			String longer = s1.length() > s2.length() ? s1 : s2;
			if (longer.length() > res.length()) {
				res = longer;
			}
		}

		return res;
	}

	private String longestPString(String s, int i, int j) {
		int low = 0, high = s.length() - 1;

		while (i >= low && j <= high) {
			if (s.charAt(i) != s.charAt(j)) {
				break;
			}
			--i;
			++j;
		}

		return s.substring(i + 1, j);
	}

	// Manacher算法
	public String longestPalindrome2(String s) {
		if (s == null || s.length() == 0) {
			return "";
		}
		// fill $ and #
		String filled = filledString(s);

		int len = filled.length();
		int[] r = new int[len];
		r[0] = 1;
		int center = 0, maxR = 0;

		for (int i = 1; i < len; i++) {
			int maxLeft = center + maxR;
			if (i < maxLeft) {
				r[i] = Math.min(r[2 * center - i], maxLeft - i);
			} else {
				r[i] = 1;
			}
			// max expand
			while (i - r[i] >= 0 && i + r[i] < len
					&& filled.charAt(i - r[i]) == filled.charAt(i + r[i])) {
				++r[i];
			}
			if (r[i] > maxR) {
				maxR = r[i];
				center = i;
			}
		}

		return removeSign(filled.substring(center - maxR + 1, center + maxR));
	}

	private String removeSign(String s) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c == '#') {
				continue;
			}
			sb.append(c);
		}
		return sb.toString();
	}

	private String filledString(String s) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < s.length(); i++) {
			sb.append("#");
			sb.append(s.charAt(i));
		}
		sb.append("#");
		return "$" + sb.toString();
	}
}

Manacher算法图解

posted @ 2015-07-27 11:04  Chapter  阅读(180)  评论(0编辑  收藏  举报