【leedcode】 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.

https://leetcode.com/problems/longest-palindromic-substring/

求最大回文的长度,其实这道题比上一道有意思。

方法1 循环查询 (该方案为O(N*N*N))

public static boolean isPalindrome(String s, int start, int end) {
		if (((end - start) & 0x1) == 1) {
			while (start + 1 != end) {
				if (s.charAt(start++) != s.charAt(end--)) {
					return false;
				}
			}
			return s.charAt(start) == s.charAt(end);
		} else {
			while (start != end) {
				if (s.charAt(start++) != s.charAt(end--)) {
					return false;
				}

			}
		}

		return true;
	}

	public static String longestPalindrome_1(String s) {
		int len = s.length();
		if (len < 2) {
			return s;
		}
		for (int i = 0, end=len/2; i < end; i++) {
			for (int j = len - 1, k = i; k > -1; j--, k--) {
				if (k == j && j == i) {
					return "";
				}
				if (isPalindrome(s, k, j)) {
					return s.substring(k, j + 1);
				}
			}
		}

		return "";
	}

方法2 动态规划 (该方案为O(N*N))

由于没学过动态规划,特意去学习了一下

/**
	 *
	 * 1. 初始条件:
空串 看作是回文的最初始条件,LP[i][i-1]=1。这作为初始状态,并不认为是有回文。
单字符串 是直接认为有回文的,LP[i][i]=1。
2. 状态转移:
若LP[i][j]=1且a[i-1]==a[j+1] ,那么有LP[i-1][j+1]=1,否则LP[i-1][j+1]=0
	 * @param s
	 * @return
	 */
	public static String longestPalindromeDP_2(String s) {
		int n = s.length();
		int longestBegin = 0;
		int maxLen = 1;
		boolean[][] table = new boolean[n][n];
		// 单字符
		for (int i = 0; i < n; i++) {
			table[i][i] = true;
		}
		// 双字符
		for (int i = 0; i < n - 1; i++) {
			if (s.charAt(i) == s.charAt(i + 1)) {
				table[i][i + 1] = true;
				longestBegin = i;
				maxLen = 2;
			}
		}
		// 子串长度
		for (int len = 3; len <= n; len++) {
			// 子串的起始位置
			for (int i = 0; i < n - len + 1; i++) {
				// 子串的结束位置
				int j = i + len - 1;
				// DP条件
				if (table[i + 1][j - 1] && s.charAt(i) == s.charAt(j) ) {
					table[i][j] = true;
					longestBegin = i;
					maxLen = len;
				}
			}
		}
		return s.substring(longestBegin, longestBegin + maxLen);
	}

方法3 中心扩展,方法1的优化版本 (该方案为O(N*N))

static class Pair {
		int s;
		int e;

		public Pair(int s, int e) {
			this.s = s;
			this.e = e;
		}

		int length() {
			return e - s + 1;
		}
	}

public static Pair expandAroundCenter2(String s, int c1, int c2) {
		int l = c1, r = c2;
		int n = s.length();
		while (l > -1 && r < n && s.charAt(l) == s.charAt(r)) {
			l--;
			r++;
		}
		return new Pair(l + 1, r);
	}

	public static String longestPalindromeSimple2(String s) {
		int n = s.length();
		if (n == 0)
			return "";
		Pair longest = new Pair(0, 1); // a single char itself is a
											// palindrome
		int i = 0;
		// 偶回文
		Pair p2 = expandAroundCenter2(s, i, i + 1);
		if (p2.length() > longest.length())
			longest = p2;
		for (i = 1; i < n - 1; i++) {
			// 奇回文
			Pair p1 = expandAroundCenter2(s, i, i);
			if (p1.length() > longest.length())
				longest = p1;
			// 偶回文
			p2 = expandAroundCenter2(s, i, i + 1);
			if (p2.length() > longest.length())
				longest = p2;
		}
		return s.substring(longest.s,longest.e);
	}

方法.后缀数组, logN * O(n)

方法5.Manacher算法, O(n)

// ^ and $ 避免空指针
	 static StringBuilder preProcess(String s) {
		int n = s.length();
		StringBuilder buff = new StringBuilder("^");
		for (int i = 0; i < n; i++) {
			buff.append("#").append(s.charAt(i));
		}
		buff.append("#$");
		return buff;
	}
public static String longestPalindrome(String s) {
		if (s.length() < 2) {
			return s;
		}
		// 插入到^#c#a#b#b#a#$
		StringBuilder T = preProcess(s);
		int length = T.length();
		int[] p = new int[length]; //存储每一个位置的长度
		int C = 0, R = 0;

		for (int i = 1; i < length - 1; i++) {

			int i_mirror = C - (i - C);
			int diff = R - i;
//			prettyPrint(T, C, R, i, i_mirror, p);
			if (diff >= 0)// 当前i在C和R之间,可以利用回文的对称属性
			{
				// R 能移动已经判断是相等过
				if (p[i_mirror] < diff)// i的对称点的回文长度在C的大回文范围内部
				{
					p[i] = p[i_mirror];
//					System.out.println(T.charAt(i_mirror) + "<<$>>"+ T.charAt(i));
				} else {
					p[i] = diff;
					// i处的回文可能超出C的大回文范围了
					while (T.charAt(i + p[i] + 1) == T.charAt(i - p[i] - 1)) {
						p[i]++;
					}
					C = i;
					R = i + p[i];
				}
			} else {
				p[i] = 0;
				while (T.charAt(i + p[i] + 1) == T.charAt(i - p[i] - 1)) {
					p[i]++;
				}
				C = i;
				R = i + p[i];
			}
		}

		int maxLen = 0;
		int centerIndex = 0;
		// 最大的索引
		for (int i = 2; i < length - 1; i+=1) {
			if (p[i] > maxLen) {
				maxLen = p[i];
				centerIndex = i;
			}
		}
		// 计算起始地址
		centerIndex = (centerIndex - 1 - maxLen) / 2;
		return s.substring(centerIndex, centerIndex + maxLen);
	}

  

时间: 2024-10-24 12:54:47

【leedcode】 Longest Palindromic Substring的相关文章

【LeetCode】Longest Palindromic Substring 解题报告

DP.KMP什么的都太高大上了,自己想了个朴素的遍历方法. [题目] 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. [思路](应该算是O(n)吧) 从中间向两端搜索,分别找到以每个字母为中心的最长

【Leetcode】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 class Solution { 2 public: 3 string longestPalind

LeetCode【5】. Longest Palindromic Substring --java实现

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. 题目要求给定字符串的最大对称子字符串,如"aaabccbac

Leetcode:【DP】Longest Palindromic Substring 解题报告

Longest Palindromic Substring -- HARD 级别 Question SolutionGiven 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. 经典的DP题目. 主页君给出3种解

【leetcode】Longest Palindromic Substring (middle) 经典

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. 动态规划解法 O(n2) 超时 string longestPalindrome(string s) { if(s.empty()) return s

【翻译】Longest Palindromic Substring 最长回文子串

原文地址: http://www.cnblogs.com/zhxshseu/p/4947609.html%20 转载请注明出处:http://www.cnblogs.com/zhxshseu/p/4947609.html 问题描述:Given a string S, find the longest palindromic substring in S. 这道题目是一个经典的动态规划DP http://challenge.greplin.com/问题,在面试中经常会被问到.为什么?因为这个问题可

【SPOJ】Longest Common Substring II (后缀自动机)

[SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记录\(f[i]\)表示走到了\(i\)节点 能够匹配上的最长公共子串的长度 当然,每个串的\(f[i]\)可以更新\(f[i.parent]\) 所以需要拓扑排序 对于每个串求出每个节点的最长匹配 然后对他们取\(min\),表示某个节点大家都能匹配的最长长度 最后对于所有点的值都取个\(max\)

【SPOJ】Longest Common Substring(后缀自动机)

[SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另外一个串在\(SAM\)上不断匹配 最后计算答案就好了 匹配方法: 如果\(trans(s,c)\)存在 直接沿着\(trans\)走就行,同时\(cnt++\) 否则沿着\(parent\)往上跳 如果存在\(trans(now,c),cnt=now.longest+1\) 否则,如果不存在可行的

【SPOJ】Longest Common Substring

[SPOJ]Longest Common Substring 求两个字符串的最长公共子串 对一个串建好后缀自动机然后暴力跑一下 废话 讲一下怎么跑吧 从第一个字符开始遍历,遍历不到了再沿着\(parents\)走看能否找到出路,走到某个点时,统计一下走过了多少点然后更新答案 来说说这样做的正确性: 遍历是肯定的, PAM 从根节点出发的任意路径都表示一个子串 沿着\(parents\)边往后走,保证贪心情况下维护最长公共子串寻找出路 注意这里是统计走过了多少点更新答案,不能直接通过\(len\)