原题目:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
给定一个字符串,求出该字符串最长的回文子串。
算法分析:
算法2:马拉车算法,时间复杂度:O(N),空间复杂度:O(N)
详见马拉车算法的博文
算法3:动态规划算法,时间复杂度:O(N^2),空间复杂度:O(N^2)
此题还可以用动态规划Dynamic Programming来解,我们维护一个二维数组dp,其中dp[i][j]表示字符串区间[i, j]是否为回文串,当i = j时,只有一个字符,肯定是回文串,如果i = j + 1,说明是相邻字符,此时需要判断s[i]是否等于s[j],如果i和j不相邻,即i - j >= 2时,除了判断s[i]和s[j]相等之外,dp[j + 1][i - 1]若为真,就是回文串,通过以上分析,可以写出递推式如下:
dp[i, j] = 1 if i == j
= s[i] == s[j] if j = i + 1
= s[i] == s[j] && dp[i + 1][j - 1] if j > i + 1
- dp[i][j] 表示子串s[i…j]是否是回文
- 初始化:dp[i][i] = true (0 <= i <= n-1); dp[i][i-1] = true (1 <= i <= n-1); 其余的初始化为false
- dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true)
遇到问题:
有点多啊,慢慢看程序吧
LeetCode提交源码:
算法2:
public String longestPalindrome(String s) {
StringBuilder stringBuilder = new StringBuilder("$");
for(char c : s.toCharArray()){
stringBuilder.append("#");
stringBuilder.append(c);
}
stringBuilder.append("#");
String str = stringBuilder.toString();
System.out.println("str=" + str);
int center = 0; //中心位置
int rightMax = 0;
int index = 0;
int maxLength = 0;
int[] p = new int[str.length()];
for(int i = 1;i < str.length();i++){
int j = 2*center -i;
//p[i] = rightMax > i ? Math.min(p[symmetryId],rightMax - i) : 1;
if(rightMax > i){
if(p[j] < rightMax - i)
p[i] = p[j];
else
p[i] = rightMax - i;
}else{
p[i] = 1;
}
while (i + p[i] < str.length() && str.charAt(i + p[i]) == str.charAt(i - p[i])) {
p[i]++;
}
if (i + p[i] > rightMax) {
center = i;
rightMax = i + p[i];
}
if (p[i] > maxLength) {
maxLength = p[i];
index = i;
}
}
return s.substring((index - maxLength) / 2, (index + maxLength) / 2 - 1);
}
LeetCode提交源码:
算法4:
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) {
return "";
}
int length = s.length();
int max = 0;
String result = "";
for(int i = 1; i <= 2 * length - 1; i++){
int count = 1;
while(i - count >= 0 && i + count <= 2 * length && get(s, i - count) == get(s, i + count)){
count++;
}
count--; // there will be one extra count for the outbound #
if(count > max) {
result = s.substring((i - count) / 2, (i + count) / 2);
max = count;
}
}
return result;
}
private char get(String s, int i) {
if(i % 2 == 0)
return '#';
else
return s.charAt(i / 2);
}
完整运行程序:
/**************************************************************
* Copyright (c) 2016
* All rights reserved.
* 版 本 号:v1.0
* 题目描述: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.
* Input: "babad"
* Output: "bab"
* Note: "aba" is also a valid answer.
* 给定一个字符串,求出其中的最长回文子串
* 输入描述:请输入一个包含回文的字符串:
* aaaba
* 程序输出: str=$#a#a#a#b#a#
* 最长的回文串为:aaa
* 问题分析:无
* 算法描述:算法2:马拉车算法,时间复杂度:O(N),空间复杂度:O(N)
* 算法3:动态规划算法, 时间复杂度:O(N^2),空间复杂度:O(N^2)
* 完成时间:2016-11-13
***************************************************************/
package org.GuoGuoFighting.LeetCode05;
import java.util.Scanner;
class SolutionMethod1{
/*public String longestPalindrome(String s) {
if(s == null){
return null;
}
char[] ch = s.toCharArray();
int i = 0;
int j = 1;
char[] newch = new char[ch.length];
while(i < ch.length){
for(;j < ch.length; j++){
if(ch[i] == ch[j]){
break;
}
}
}
}*/
}
/*
算法2:马拉车算法 Manacher's ALGORITHM
时间复杂度:O(N)
空间复杂度:O(N)
*/
class SolutionMethod2{
public String longestPalindrome(String s) {
StringBuilder stringBuilder = new StringBuilder("$");
for(char c : s.toCharArray()){
stringBuilder.append("#");
stringBuilder.append(c);
}
stringBuilder.append("#");
String str = stringBuilder.toString();
System.out.println("str=" + str);
int center = 0; //中心位置
int rightMax = 0;
int index = 0;
int maxLength = 0;
int[] p = new int[str.length()];
for(int i = 1;i < str.length();i++){
int j = 2*center -i;
//p[i] = rightMax > i ? Math.min(p[symmetryId],rightMax - i) : 1;
if(rightMax > i){
if(p[j] < rightMax - i)
p[i] = p[j];
else
p[i] = rightMax - i;
}else{
p[i] = 1;
}
while (i + p[i] < str.length() && str.charAt(i + p[i]) == str.charAt(i - p[i])) {
p[i]++;
}
if (i + p[i] > rightMax) {
center = i;
rightMax = i + p[i];
}
if (p[i] > maxLength) {
maxLength = p[i];
index = i;
}
}
return s.substring((index - maxLength) / 2, (index + maxLength) / 2 - 1);
}
}
/*
算法3:动态规划算法
时间复杂度:O(N^2)
空间复杂度:O(N^2)
*/
class SolutionMethod3{
public String longestPalindrome(String s) {
if(s.length() == 0){
return "";
}
if(s.length() == 1){
return s;
}
/*int length = s.length();
boolean[][] dp = new boolean[length][length];
int resleft = 0;
int resright = 0;
int i,j;
for( i = 0; i < s.length(); i++){
for( j = 0; j < length; j++){
if(i >=j){
dp[i][j] = true;
}
else{
dp[i][j] = false;
}
}
}
int maxLen = 1;
for(int k = 1; k < s.length(); k++){
for( i = 0; k +i < length; i++){
j = i + k;
if(s.charAt(i) != s.charAt(j)){
dp[i][j] = false;
}
else{
dp[i][j] = dp[i+1][j-1];
if(dp[i][j]){
if(k + 1 > maxLen){
maxLen = k + 1;
resleft = i;
resright = j;
}
}
}
}
}
return s.substring(resleft,resright+1);*/
int maxLength = 0;
String longest = null;
int length = s.length();
boolean[][] table = new boolean[length][length];
// 单个字符都是回文
for (int i = 0; i < length; i++) {
table[i][i] = true;
longest = s.substring(i, i + 1);
maxLength = 1;
}
// 判断两个字符是否是回文
for (int i = 0; i < length - 1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
table[i][i + 1] = true;
longest = s.substring(i, i + 2);
maxLength = 2;
}
}
// 求长度大于2的子串是否是回文串
for (int len = 3; len <= length; len++) {
for (int i = 0, j; (j = i + len - 1) <= length - 1; i++) {
if (s.charAt(i) == s.charAt(j)) {
table[i][j] = table[i + 1][j - 1];
if (table[i][j] && maxLength < len) {
longest = s.substring(i, j + 1);
maxLength = len;
}
} else {
table[i][j] = false;
}
}
}
return longest;
}
}
class SolutionMethod4{
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) {
return "";
}
int length = s.length();
int max = 0;
String result = "";
for(int i = 1; i <= 2 * length - 1; i++){
int count = 1;
while(i - count >= 0 && i + count <= 2 * length && get(s, i - count) == get(s, i + count)){
count++;
}
count--; // there will be one extra count for the outbound #
if(count > max) {
result = s.substring((i - count) / 2, (i + count) / 2);
max = count;
}
}
return result;
}
private char get(String s, int i) {
if(i % 2 == 0)
return '#';
else
return s.charAt(i / 2);
}
}
public class LongestPalindromicSubstring {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个包含回文的字符串:");
String str = scanner.nextLine();
scanner.close();
SolutionMethod2 solution2 = new SolutionMethod2();
System.out.println("算法2输出的最长回文串为:" + solution2.longestPalindrome(str));
SolutionMethod3 solution3 = new SolutionMethod3();
System.out.println("算法3输出的最长回文串为:" + solution3.longestPalindrome(str));
SolutionMethod4 solution4 = new SolutionMethod4();
System.out.println("算法4输出的最长回文串为:" + solution4.longestPalindrome(str));
}
}
程序运行结果: