<LeetCode OJ> 5. Longest Palindromic Substring

Total Accepted: 107892  Total Submissions: 466359  Difficulty: Medium

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.


分析:DONE

这是一个很经典的,证明算法魅力的实例。这里只打算掌握动态规划解法,那种线性时间的Manacher解法实在难想(像KMP算法一样先进行预处理),说真的,没必要浪费时间在这种稀奇古怪的解法上


实际上在做的时候知道该怎么设定子问题,怎么初始化,但是却在怎么遍历迷糊了很久。

以下为别人的算法设计:

定义子问题:dp[i][j] 表示子串s[i…j]是否是回文,我们这样定义实际上变相知道了当前回文子串的长度,以及在原字符串中的位置。
1,初始化:
1),dp[i][i] = true (0 <= i <= n-1);
2),if(s[i]==s[i+1]), dp[i][i+1] = true (0 <= i <= n-2);
3),其余的初始化为false

2,在初始化基础上的递推过程
如果子问题dp[i+1][j-1] == true,并且扩张一个位置后s[i] == s[j]
显然当前位置,dp[i][j] = true,否则还是为false(意义就是,小的子串都不是回文,在此基础上更大的子串也不是回文)
在动态规划中更新最长回文的长度及起点以及长度即可

 

3,关于如何遍历的思考

从大的方向上来考虑:动态规划是自底向上的递推过程,即由较小规模的子问题遍历到原问题。

首先我们的原问题是什么?在给定字符串s中寻找最长的回文。

那么他的较小规模的子问题是什么?正如前面别人家的分析所知,我们必须先知道较短长度s.size()-2的子串是否是回文,那么s.size()的源字符串就可以被判断出来

接着唠嗑,为了判断“较短长度s.size()-1的子串是否为回文”,我们必须先知道较短长度s.size()-3的子串是否是回文,那么s.size()-1的源字符串就可以被判断出来

接着唠嗑,为了判断“较短长度s.size()-2的子串是否为回文”,我们必须先知道较短长度s.size()-4的子串是否是回文,那么s.size()-2的源字符串就可以被判断出来

...............

显然循环的最外层就是当前要判断的子串的长度,由小到大。

循环的最内层就是遍历当前指定子串长度的起点和终点,

而最长的回文在我们遍历的过程更新即可!


间复杂度为O(N*N),时间复杂度为O(1)

class Solution {
public:
    string longestPalindrome(string s) {
        const int strLen = s.size();  
        int begin = 0;  int maxLen = 1;  
        bool table[1000][1000] = {false}; 
        //前期的初始化1: 独立的一个字符也是回文啊
        for (int i = 0; i < strLen; i++)     
            table[i][i] = true;   
        //前期的初始化2:两个相等的相邻字符当然也是(吐槽,不能通过递推获取,所以只能单独拿出来初始化)
        for (int i = 0; i < strLen-1; i++) 
        {   
            if (s[i] == s[i+1]) 
            {      
                table[i][i+1] = true; 
                begin = i;      
                maxLen = 2;    
            }  
        }
        //递推3:寻找长度为3及其以上的回文子串
        for (int len = 3; len <= strLen; len++) //当前子串的长度len
        {    
            for (int i = 0; i < strLen-len+1; i++) //当前子串起始位置i
            {      
                int j = i+len-1; //子串末尾位置j     --》j-i=len-1
                if (s[i] == s[j] && table[i+1][j-1]) 
                {        
                    table[i][j] = true;        
                    begin = i;        
                    maxLen = len;      
                }    
            }  
        }  
        return s.substr(begin, maxLen);
    }
};


注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!

原文地址:http://blog.csdn.net/ebowtang/article/details/50698672

原作者博客:http://blog.csdn.net/ebowtang

本博客题解索引:http://blog.csdn.net/ebowtang/article/details/50668895

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值