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.
首先,所谓回文,其实就是反过来和原来的字符串一样。
解题的第一个想法是遍历整个字符串,查看以字符为中心的最长回文。但是回文有2种不同形态。一种是偶数的一种是基数的。所以复杂度较高。
看到很多人介绍的另一种方法是用manacher算法:这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方。这个算法还有一个很好的地方就是充分利用了字符匹配的特殊性,避免了大量不必要的重复匹配。
算法大致过程是这样。先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用‘#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组P记录以每个字符为中心的最长回文串的信息。P[id]记录的是以字符str[id]为中心的最长回文串,当以str[id]为第一个字符,这个最长回文串向右延伸了P[id]个字符。
原串: w aa bwsw f d
新串: # w# a # a #
b# w # s # w # f # d #
辅助数组P: 1 2 1 2 3 2 1 2 1 2 1 4 1 2 1 2 1 2
1
这样可以通过辅助数组P可以知道最长回文的中心文字,这样就可以查找出起始和结束位置。
public class Solution {
public String longestPalindrome(String s) {
int length = s.length();
char[] ch = new char[2*length + 1];
int[] p = new int[2*length + 1];
char[] c = s.toCharArray();
int i = 0;
while(i<2*length)
{
ch[i] = ‘#‘;
ch[i+1] = c[i/2];
i = i + 2;
}
ch[2*length] = ‘#‘;
i = 0;
while(i<2*length + 1)
{
p[i] = findPali(ch,i);
i++;
}
int maxIndex = 0;
i = 1;
while(i<2*length+1)
{
if(p[i]>p[maxIndex])
{
maxIndex = i;
}
i++;
}
int start = maxIndex - p[maxIndex] + 1;
int end = maxIndex + p[maxIndex] - 1;
char[] result = new char[(end - start)/2];
i = 0;
while(start<=end)
{
if(ch[start]!=‘#‘)
{
result[i] = ch[start];
i++;
}
start++;
}
String longest = new String(result);
return longest;
}
public int findPali(char[] ch,int index)
{
int length = ch.length;
int i = 1;
while((index + i<length)&&(index-i>=0)&&(ch[index - i] == ch[index + i]))
{
i++;
}
return i;
}
}
leetcode:Longest Palindromic Substring,布布扣,bubuko.com
leetcode:Longest Palindromic Substring
原文地址:http://www.cnblogs.com/jessiading/p/3736577.html