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.

面DP题的考官都是神经病。

。(吐槽)

貌似挺easy出回文的题,那么今天细致分析下DP的做法!!

以解我被DP问题虐成渣渣的心碎感觉。如有错误请指出~

首先。拿了这个题,至少也能够给出一个O(n^3)的算法。2层for循环加每次检查一遍substring是不是回文。

我给出了一个必然超时的代码以供參考。

public String longestPalindrome(String s) {
if(s==null) return null;
// String[][] dp= new String[1000][1000];
// Arrays.fill(dp,1);
int max=1;
String result=s.substring(0,1);
for(int i=0;i<s.length()-1;i++){
for(int j=i+1;j<s.length();j++){
String temp=s.substring(i,j+1);
if(ifPalin(temp)){
if(max<temp.length()){
max=temp.length();
result=temp;
}
if(max==s.length())
return result;
}
}
} return result; } public boolean ifPalin(String s){
if(s==null) return true;
int start=0;
int end=s.length()-1; while(start<end){
if(s.charAt(start++)!=s.charAt(end--)){
return false;
}
} return true;
}

这显然不够。怎样优化?你会想到这样的恶心题。dp那是必定的。

那么要分析回文。必定要考虑到全部的情况。

↑上面Naive的方法超时原因是由于:每次循环,都得看一遍当前子串是不是回文,那么怎样解决这样的反复性的工作呢?

通过对回文性质的分析。我们能够看出来: 假设中间的某一段子串sub是回文,假设sub两側的字符是一样的。那么作为一个总体也是回文。

比如:

abcdcba      : d是回文,cdc那么就是回文。 假设你再想一下。cdc是回文。两側b是一样的,bcdcb也是回文。咦,那么abcdcba就是回文了呗。

通过上个样例我们直接知道了答案。这是特例,那么对于普通情况怎样是好呢?所以第一个思路就是依据顺向的思维推导出来的:

我们申明一个dp[][]来储存状态。 对于dp[i][j]来说, 其意义就是 s.substring(i,j+1)是不是回文。

(1)既然我们不知道哪里为中心。向外拓展就能得到答案。

那么就以每一个字符为中心,向外拓展,保存一个最大的量,问题就攻克了!

我们得初始化下dp, 单个字符是,所以dp[i][i]=true.

但是还有种情况。 abcddcba,中间是两个。不是一个,这也能构成回文,这怎么办。

事实上也好办。我们就看看s.charAt(i)==s.charAt(i+1),假设是,就是回文。我们就set  dp[i][i+1]=true

有了基础的case,我们1层for循环移动中心点,用两个指针start,end,分别拓展这两种情况,来分析回文。就可以找出最大值。

代码例如以下:

 public String longestPalindrome(String s) {
if(s==null) return null;
boolean[][] dp= new boolean[s.length()][s.length()];
//define dp[i][j] is if s.substring(i,j+1) is palindrome:
int max=1;
String result=s.substring(0,1);
for(int i=0;i<s.length();i++){
dp[i][i]=true;
}
for(int i=0;i<s.length()-1;i++){
if(s.charAt(i)==s.charAt(i+1)){
dp[i][i+1]=true;
result=s.substring(i,i+2);
max=2;
}
}
for(int i=1;i<s.length()-1;i++){
int start=i-1,end=i+1; //aba的情况
while(start>=0 && end<=s.length()-1){
if(dp[i][i] && s.charAt(start)==s.charAt(end)){
dp[start][end]=true;
if(max<end-start+1){
max=end-start+1;
result=s.substring(start,end+1);
}
} else {
break;
}
start--;end++;
}
start=i-1;end=i+2; //abba的情况
while(start>=0 && end<=s.length()-1){
if(dp[i][i+1] && s.charAt(start)==s.charAt(end)){
dp[start][end]=true;
if(max<end-start+1){
max=end-start+1;
result=s.substring(start,end+1);
}
} else{
break;
}
start--;end++;
}
} return result; }

上面的代码啰嗦了点。应该能简化,我比較懒。。假设理解意思了就好办!

(2)上面的解法事实上不太算dp,我们来考虑下真正的dp解法,但这个有时候非常难想出来。。多琢磨吧。。

至少。假设你看到了这。耐心点再看一些。一定会理解dp解这个题的过程:

dp的思路是用曾经做出来的结果作为基础,然后推导出新的结果。(2)的思路是:利用回文的性质,假设推断dp[i][j]是不是回文。那么要具备什么?

答案是:

1. s.charAt(i)==s.charAt(j)

2. dp[i+1][j-1] 是否为真

(这个代表当前的s.substring(i,j+1)往里面缩一个的substring是否是回文,有点绕。。举例: abccbfee, 假设i=0,j=5,也就是abccbf,dp[i][j]就是说abccbf是不是回文,依据之前的结果,假设s.charAt(i)==s.charAt(j),而且。bccb也是回文,那么dp[i][j]就为真. 这个样例中 a!=f, 尽管dp[i+1][j-1]
(bccb)是回文,那也不能算真)

所以这样dp的精华就体现出来了:通过之前的结果,推导如今!

还有个关键点。就是dp的写法。下午我把dp数组打印了出来,横坐标i从后往前。j是从i 到最后。1代表true,是回文,0反之。

dp里面挺多是从后面来的,当然我们不能记结果,而是要明确为什么这么做。

   

回文的中心多数应该是在中心位置,所以。从后往前走,我们能够利用到之前的结果。 (从前往后走也是一样的,仅仅只是循环的參数要对应的变一下)

然而是上面的条件还不够!假设说dp[i+1][j-1]为假。

但当i和j位置的字符是一致的,而且距离小于等于2的时候,那都是回文,原因是仅仅有3种情况: a (i=j)  aa (i=0,j=1) a*a(i=0,j=2)  *表示随意字符. 所以这样我们能够当做回文。

接着i不动,j接着走,超出了2的距离,也有可能会遇到和i一样的字符,这时候是不是回文?那就得看dp[i+1][j-1]是不是回文,假设是。记录,推断是否超过当前最大长度。

假设超过就替换最长字符串。

看第二张图,那三个1,事实上就是样例中 abccbadd的推导过程, 当i=2的循环。j=2。是回文,记录。 i=2, j=3,“cc” 是回文,继续。 "ccb"不是回文,

以上就是所有的分析,建议看文章的童鞋自己推导一遍过程。仅仅有理解了为什么这么做,才干真正理解dp。从而写出出精炼干净的dp代码

:以下代码是从大神那看到的,拿过来的。

    public String longestPalindrome(String s) {
if(s==null || s.length()==1) return s;
boolean[][] dp= new boolean[s.length()][s.length()];
//define dp[i][j] is if s.substring(i,j+1) is palindrome:
int max=0;
String result=s.substring(0,1);
for(int i=s.length()-1;i>=0;i--){
for(int j=i;j<s.length();j++){
if(s.charAt(i)==s.charAt(j) && ((j-i<=2) || dp[i+1][j-1])){
dp[i][j]=true;
if(max<j-i+1){
max=j-i+1;
result=s.substring(i,j+1);
}
}
}
}
return result;
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

[LeetCode] Longest Palindrome Substring 具体分析的更多相关文章

  1. G.Longest Palindrome Substring

    链接:https://ac.nowcoder.com/acm/contest/908/G 题意: A palindrome is a symmetrical string, that is, a st ...

  2. 5.Longest Palindrome substring

    /* * 5.Longest Palindrome substring * 2016-4-9 by Mingyang 自然而然的想到用dp来做 * 刚开始自己做的时候分的条件太细,两个index相等, ...

  3. Leetcode: Longest Palindromic Substring && Summary: Palindrome

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  4. [LeetCode] Longest Palindromic Substring 最长回文串

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  5. [LeetCode] Longest Palindrome 最长回文串

    Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...

  6. Leetcode Longest Palindromic Substring

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  7. LeetCode:Longest Palindromic Substring 最长回文子串

    题目链接 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  8. [LeetCode] Longest Palindromic Substring(manacher algorithm)

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  9. LeetCode Longest Palindrome

    原题链接在这里:https://leetcode.com/problems/longest-palindrome/ 题目: Given a string which consists of lower ...

随机推荐

  1. sql语句用'in'执行多条语句时候,执行错误的解决方法

    一般报错是出现,无法将nvarchar类型转换为int类型 这是因为 SqlParameter  带参数  是不能用  , 分割的. 第一种解决方法就是  不用 SqlParameter  带参数的s ...

  2. 发展合作-ASP.Net传递页面之间的值

    在合作开发中,在页面串传值的时候,遇到了一些困难.在网上搜罗了一下,发现好多的传值方式,能够简单地分下面三种. 一. URL传值 原页面的值放到目标页面的URL中.然后通过QueryString方法获 ...

  3. quick-cocos2d-x游戏开发【7】——scheduler 定时器

    定时器用的地方还是比較多的,游戏中的逻辑推断非常多都是採用每帧运行.quick对于schedule的封装在scheduler这个lua文件里.假设是第一次接触quick的话,可能依照官方的api来写一 ...

  4. oracle分区表运行计划

    分区表有非常多优点,以大化小,一小化了,加上并行的使用,在loap中能往往能提高几十倍甚至几百倍的效果. 当然表设计得不好也会适得其反.效果比普通表跟糟糕. 为了更好的使用分区表,这里看一下分区表的运 ...

  5. bellman_ford算法

    给定一个源点,求最短路径,那么存在以源点为根的最短路径树因为最短路径具有最优子结构的性质,所以我们可以先求出树的第一层,然后再求出树的第二层,以此类推bellman_ford算法就是按照这种思想求最短 ...

  6. ASP.NET Core MVC Hello World

    ASP.NET Core 现在ASP.NET Core还在不断成长.更新中,说不定到了明天又换了个模样,就如同一个小孩,从蹒跚学步,到奔向未来. 所以我们可以相应的去理解更新中所发生的变化,包容它.呵 ...

  7. Java并发学习之中的一个——线程的创建

    本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.与每一个Java语言中的元素一样,线程是对象.在Java中,我们有两种方式创建线程: a.通过直接继承thread类,然后覆盖run方法. b ...

  8. HDU-3502-Huson&#39;s Adventure Island(BFS+如压力DP)

    Problem Description A few days ago, Tom was tired of all the PC-games, so he went back to some old F ...

  9. hdu3530Subsequence rmq

    //使用rmq办,ma[i][j],同i作为一个起点2^j阵列的最大长度值 //启动枚举问最长的子列 //枚举的最大长度2^(j-1)和2^(j)z之间 //然后在该范围内找到 #include< ...

  10. Spring MVC 基础

    Spring MVC 基础 1.Web MVC基础 MVC的本质是表现层模式,我们以视图模型为中心,将视图和控制器分离出来.就如同分层模式一样,我们以业务逻辑为中心,把表现层和数据访问层代码分离出来是 ...