Longest Palindromic Substring
让我头疼死的一道题。
最早想到的方法:
首先用一个函数判断某字符串是否为回文串。
然后以每个字符为起点,得到其长度为 1 ~ strlen长度的子串,判断其是否为回文串,并将最大值保存在max字段中。
仔细考虑其复杂度:
选取每个字符:o(n)
选取每个字符为起始的子串:o(n)
判断子串是否为回文串:o(m) m表示子串的长度。
最后在最坏情况下的复杂度应该是o(n*n*n),提交过后果然超时。。
贴出超时代码以供交流:
struct CmpByValue {
bool operator()(const pair<string,int>& lhs, const pair<string,int>& rhs) {
return lhs.second < rhs.second;
}
}; //比较对象
class Solution {
private:
bool isPalindrome(string s)
{
int strLen = s.length();
int i;
int j = strLen-1;
int flag = 1;
if(strLen<=1)
{
return false;
}
for(i=0;i<(strLen+1)/2;i++)
{
if(s[i]!=s[j--])
flag = 0;
}
return (flag==1)?true:false;
}
public:
string longestPalindrome(string s) {
map<string,int>myMap;
string sub;
//C++ substr(size_t pos = 0, size_t len = npos)
int strLen = s.length();
int i;
int j;
if(strLen == 1)
{
return s;
}
for(i=0;i<strLen;i++)
{
for(j=strLen-1;j>=i;j--)
{
sub = s.substr(i,j+1);
if(isPalindrome(sub))
{
myMap[sub]=sub.length();
break;
}
}
}
vector< pair<string,int> >myVec(myMap.begin(),myMap.end());
sort(myVec.begin(),myVec.end(),CmpByValue());
return (myVec.end()-1)->first;
}
};
上述最原始的思路考虑的比较复杂还用到了map啊排序啊之类,后来将这些去掉,直接求最大值,还是超时。。。
后来网上看到有三种方法:
中心扩张
dp
Manacher算法
后两种方法没有仔细去研究,但是以我自己现有的水平,就只能用第一种方式来解决了,复杂度为o(n*n)
思路就是:
以某个字符为中心向两边扩张,来判断是否是回文串,并返回该子串。
当然需要考虑奇数和偶数的情况,即:aba 和 aabb的情况
代码:
class Solution {
private:
string subPalindrome(string s,int left,int right)
{
int strLen = s.length();
while(left>=0&&right<strLen && s[left]==s[right])
{
left--;
right++;
}
left++;
right--;
return s.substr(left,right-left +1);
}
public:
string longestPalindrome(string s) {
//Map<string,int>myMap;
int i;
int strLen = s.length();
string sub;
string sub1;
int max = 0;
int subLen = 0;
string result="";
for(i=0;i<strLen;i++)
{
sub = subPalindrome(s,i,i+1);//偶数的情况
subLen = sub.length();
if(subLen > max )
{
max = subLen;
result = sub;
}
sub1 = subPalindrome(s,i,i);//奇数的情况
subLen = sub1.length();
if(subLen > max )
{
max = subLen;
result = sub1;
}
}
return result;
}
};
至此题目通过。
当然,后续通过学习另外两种方法后会继续补充博文。