Q:
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.
A;
以下解法和代码没有借阅以往任何资料,如果有更好的解法请在评论区留言
这道题的大致意思是找出一个字符串中最长的回文子串,给的字符串最大长1000,只有一个最长子串。
我拿到这道题的时候感觉跟之前一道题很像啊-我自己写的LeetCode3,一个是求最长不重复串一个是求最长回文串。上次的时间复杂度是O(n)。我在想是不是可以用二分法(也就是分治思想)变成O(logn)呢,不然这题做着是不是没啥意思了。
首先我们肯定最后要把这个字符串分割成最小子串(长度为1)返回他自己,然后父方法再查找自己,这样就没意思了,因为子串和父串的最长重复子串之间没有必然联系,最后还是要遍历一下父串的,这样算法最后复杂度还是O(nlogn),在评论里求O(logn)解法。我这里换一种思路去解O(n)解法了。
首先,回文的性质如下:
1、回文正读和倒读都是一样的字符串
2、回文串中心对称
所以第一步可能我们需要先获取所有回文串然后找大小,如何确定一个字符串是回文串呢?
关于中心对称,但是我们如何快捷的找出这个中心对称的字符串就是个难点。
我们考虑一下人是怎么识别回文串的。
1、读取字符,在脑海中形成一种数据结构存储我们读取到的字符
2、对比都读到的字符是不是和上一个或者上上个字符一致,如果一致继续对比,直到不一致得出这是一个回文串。
如果这种想法我们转换成程序:
首先需要一个for来循环字符串这样就是O(n)
其次需要另一个隐藏起来的循环来对比相似的字符串,这个复杂度怎么算。。。好尴尬。
每一步只计算关于第一次发现重复位置的对称位置是否一致的话这样复杂度就成功到O(n)了。
来,让我们写个代码看看(代码比较复杂因为写了一个类进去)
public class LongestPalindromicSubstring {
public static void main(String[] args){
char[] m = "aaaaaa".toCharArray();
System.out.println(method(m));
}
private static char[] method(char[] m) {
// TODO Auto-generated method stub
Palindromic maxP = new Palindromic();
maxP.thisLength =0;
maxP.thisFlag =0d;
ArrayList pList = new ArrayList();
for(int i =1;i=2){
if(m[i]==m[i-1]){//与相邻的相等
Palindromic p = new Palindromic();
p.thisFlag = ((double)i+(double)i-1.0d)/2.0d;
p.thisLength =1;
pList.add(p);
}
if(m[i]==m[i-2]){//隔一个与上一个相等
Palindromic p = new Palindromic();
p.thisFlag = i-1.0d;
p.thisLength =1;
pList.add(p);
}
for(Palindromic p : pList){
if(!p.isEnd){
int symmetry =((int)p.thisFlag*2)-i;
if(m[i]==m[symmetry]){
p.thisLength++;
if(symmetry==0){
p.isEnd = true;
}
}else{
p.isEnd = true;
}
}
}
}else{
if(m[i]==m[i-1]){//与相邻的相等
if(i==1){
Palindromic p = new Palindromic();
p.thisFlag = ((double)i+(double)i-1.0d)/2.0d;
p.thisLength = 1;
p.isEnd = true;
pList.add(p);
}else{
Palindromic p = new Palindromic();
p.thisFlag = ((double)i+(double)i-1.0d)/2.0d;
p.thisLength = 1;
pList.add(p);
}
}if(i==2&&m[i]==m[i-2]){//隔一个与上一个相等
System.out.println("ok");
Palindromic p = new Palindromic();
p.thisFlag = i-1.0d;
p.thisLength = 1;
pList.add(p);
}
}
}
for(Palindromic p: pList){
int length;
if(p.thisFlag/1.0d==0){
length = p.thisLength*2-1;
}else{
length = p.thisLength*2;
}
int maxlength;
if(maxP.thisFlag/1.0d==0){
maxlength = maxP.thisLength*2-1;
}else{
maxlength = maxP.thisLength*2;
}
if(length>maxlength){
maxP = p;
}
}
if(maxP.thisFlag/1.0d==0){
System.out.println(maxP);
return Arrays.copyOfRange(m, (int)maxP.thisFlag-maxP.thisLength-1, (int)maxP.thisFlag+maxP.thisLength);
}else{
System.out.println(maxP);
int flag = (int) Math.ceil(maxP.thisFlag);
return Arrays.copyOfRange(m,flag-maxP.thisLength , flag+maxP.thisLength);
}
}
static class Palindromic{
public double thisFlag = 0;
public int thisLength = 0;
public boolean isEnd = false;
@Override
public String toString() {
// TODO Auto-generated method stub
return "falg:"+thisFlag+"....."+"thisLength:"+thisLength;
}
}