leetcode 5(知识点:STL string )

来源:互联网 发布:three.js 半透明特效 编辑:程序博客网 时间:2024/05/16 07:31

题目:

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.

想法一

题目满足最有子结构性质,可以用动态规划方法求解。
使用动态规划,这样可以把时间复杂度降到O(N²),空间复杂度也为O(N²)。做法如下:
首先,写出动态转移方程。
Define P[ i, j ] ← true iff the substring Si … Sj is a palindrome, otherwise false.
P[ i, j ] ← ( P[ i+1, j-1 ] and Si = Sj ) ,显然,如果一个子串是回文串,并且如果从它的左右两侧分别向外扩展的一位也相等,那么这个子串就可以从左右两侧分别向外扩展一位。
其中的base case是
P[ i, i ] ← true
P[ i, i+1 ] ← ( Si = Si+1 )
然后,看一个例子。
假设有个字符串是adade,现在要找到其中的最长回文子串。使用上面的动态转移方程,有如下的过程:
这里写图片描述
实现的代码如下:

#include <iostream>#include <string>#include <vector>using namespace std;class Solution {public:    string longestPalindrome(string s) {    int len = s.size();    int i;    bool test[1000][1000] = {false};    int begin;    int end;    int maxsize = 1;    int maxbegin = 0;   // string maxstring;   // maxstring = s.substr(0,1);    for(i = 0; i < len; i++){        test[i][i] = true;    }    for(i = 0; i < len-1; i++){        if (s[i] == s[i+1]){            test[i][i+1] = true;            maxsize = 2;           // maxstring = s.substr(i,2);           maxbegin = i;        }    }    for(int lengthOfSubstring = 3; lengthOfSubstring <= len; lengthOfSubstring++){        for(begin = 0; begin <= len - lengthOfSubstring; begin++){            end = begin + lengthOfSubstring - 1;            if(s[begin] == s[end] && test[begin+1][end-1]==true){                test[begin][end] = true;                if(lengthOfSubstring > maxsize){                //maxstring = s.substr(begin, lengthOfSubstring);                maxsize = lengthOfSubstring;                maxbegin = begin;            }            }        }    }    return s.substr(maxbegin, maxsize);    }};

其中循环的边界需要细究(我直接写的时候出过问题),要掌握substr的用法。
如果用备注里的代码会超时,这要求我们注意编程实现的小细节。

想法二

时间复杂度为O(N²)的算法-从中间向两边展开
回文字符串显然有个特征是沿着中心那个字符轴对称。比如aha沿着中间的h轴对称,a沿着中间的a轴对称。那么aa呢?沿着中间的空字符”轴对称。
所以对于长度为奇数的回文字符串,它沿着中心字符轴对称,对于长度为偶数的回文字符串,它沿着中心的空字符轴对称。
对于长度为N的候选字符串,我们需要在每一个可能的中心点进行检测以判断是否构成回文字符串,这样的中心点一共有2N-1个(2N-1=N-1 + N)。
检测的具体办法是,从中心开始向两端展开,观察两端的字符是否相同。

#include <iostream>#include <string>#include <vector>using namespace std;class Solution {public:    string longestPalindrome(string s){        int i,j;        int slen = s.size();        int maxbegin = 0, maxlen = 1;        int begin, end, len;        //子序列奇数个        for(i = 0; i < slen; i++){            begin = end = i;            while(begin >= 0 && end < slen){                if(s[begin] == s[end]){                    begin--;                    end++;                }else{                    break;                }            }            len = end - begin - 1;            if (len > maxlen){                maxbegin = begin + 1;                maxlen = len;            }        }        //子序列偶数个        for(i = 0; i < slen-1; i++){            begin = i;            end = i+1;            while(begin >= 0 && end < slen){                if(s[begin] == s[end]){                    begin--;                    end++;                }                else{                    break;                }            }            len = end - begin - 1;            if (len > maxlen){                maxbegin = begin + 1;                maxlen = len;            }        }        return s.substr(maxbegin, maxlen);    }};

想法三

详细见参考资料,O(n)的算法:Manacher’s Algorithm, 一般人不太可能自己想到。

一种错误的想法:

想到最大子序列问题,想用类似的方法递归求解。但是经过中点的情形会很麻烦。

知识点

STL string,详细见:
http://blog.csdn.net/y990041769/article/details/8763366

参考资料:
博客:
http://blog.csdn.net/feliciafay/article/details/16984031
想法三O(n)
http://articles.leetcode.com/longest-palindromic-substring-part-ii/

0 0
原创粉丝点击