Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
思路一:穷竭暴力搜索,事件复杂度为O(N^3)
思路二:判断一个字符串是否是回文,可以通过首位两个指针分别向中间靠近来判断。但在本题中,无法判断出首位的位置。所以可以通过从中间位置不断向外扩展来判断字串是否是回文以及回文的长度。该方法的时间复杂为O(N^2)。
class Solution {
public:
string getP(string s,int l,int r)
{
int carry = 0;
int count = 0;
int left=l,right=r;
while(left>0&&right<s.length())
{
left--;right++;
if(s[left]==s[right])
count++;
else
break;
}
if(count == 0)
return s.substr(l,r-l+1);
else
return s.substr(l-count,r-l+2*count+1);
}
string longestPalindrome(string s) {
int len = s.length();
string result="";
if(len == 0)
return "";
int i;
for(i=0;i<len;i++)
{
string temp1 = getP(s,i,i);
if(temp1.length() > result.length())
result = temp1;
if(i+1 < len && s[i] == s[i+1])
{
string temp2 = getP(s,i,i+1);
if(temp2.length() > result.length())
result = temp2;
}
}
return result;
}
};
写完以后觉得代码好丑陋,对其进行优化。上面的代码调用了太多函数,消耗了很多时间。并且通过分析发现,当最中间的存在一系列相同的字符时,无论从其中哪一个字符开始,其形成的回文字串的长度都是相同的,这样可以进行一些剪枝。优化后的代码如下:
class Solution {
public:
string longestPalindrome(string s) {
int len = s.length();
string result="";
if(len == 0)
return "";
if(len == 1)
return s;
int i,l,r,start=0,max=0;
for(i=0;i<len;i++)
{
l=i-1;
r=i+1;
while(l>=0&&s[l]==s[i])
l--;
while(r<=len&&s[r]==s[i])
r++;
i=r-1;
while(l>=0&&r<=len&&s[l]==s[r])
{
l--;r++;
}
if(r-l-1>max)
{
start = l+1;
max=r-l-1;
}
}
return s.substr(start,max);
}
};
思路三:可以采用动态规划。动态规划是十分重要的方法,动态规划适用于解法存在一种递推关系的问题。以本题为例,当table[i][j]=true代表索引i到j的字串为回文,那么table[i-1][j+1]=true则需要s[i-1]==s[j+1].
定义 P[ i, j ] ← 如果子串Si … Sj 是一个回文,那么该项为true, 否则为false.
P[ i, j ] 为 true ← ( P[ i+1, j-1 ]为true,并且Si = Sj )
基本条件:
P[ i, i ] 一定是true
class Solution {
public:
string longestPalindrome(string s) {
int i;
int start = 0,max=1;
int len = s.length();
bool table[1000][1000] = {false};
for(i=0;i<len;i++)
table[i][i] = true;
for(i=0;i<len-1;i++)
{
if(s[i] == s[i+1])
{
table[i][i+1] = true;
start = i;
max = 2;
}
}
for(i=3;i<=len;i++)
for(int j=0;j<len-i+1;j++)
{
if(s[j] == s[j+i-1] && table[j+1][j+i-2] == true)
{
table[j][j+i-1] = true;
if(max < i)
{
start = j;
max = i;
}
}
}
return s.substr(start,max);
}
};
感觉实现的性能不太行啊。。。
思路四:在网上搜索发现著名的Manacher算法,事件复杂度为 O(N)