http://blog.csdn.net/kangroger/article/details/37742639
1、暴力法
最容易想到的就是暴力破解,求出每一个子串,之后判断是不是回文,找到最长的那个。
求每一个子串时间复杂度O(N^2),判断子串是不是回文O(N),两者是相乘关系,所以时间复杂度为O(N^3)。
int FindLongestPalindrome1(string s){
int maxLen = 0;
for(int i = 0; i < s.size(); i++)
{
for(int j = i; j < s.size(); j++)
{
string substr = s.substr(i, j-i+1);
int m = 0, n = substr.size()-1;
while(m <= n)
{
if(substr[m] != substr[n])
break;
else
{
m++;
n--;
}
}
if(m > n)
{
if(substr.size() > maxLen)
maxLen = substr.size();
}
}
}
return maxLen;
}
2、动态规划
回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文字符串,那么P[i+1,j-1]也是回文字符串。这样最长回文子串就能分解成一系列子问题了。这样需要额外的空间O(N^2),算法复杂度也是O(N^2)。
首先定义状态方程和转移方程:
P[i,j]=0表示子串[i,j]不是回文串。P[i,j]=1表示子串[i,j]是回文串。
则 P[i,j] = P[i+1,j-1], if(s[i]==s[j])
= 0 , if(s[i]!=s[j])
int FindLongestPalindrome2(string s)
{
int maxLen = 0;
int len = s.size();
bool **isPalindrome = new bool *[len];
for(int i = 0; i < len; i++)
isPalindrome[i] = new bool[len]();
for(int i = 0; i < len; i++)
{
isPalindrome[i][i] = true;
if(i<len-1 && isPalindrome[i]==isPalindrome[i+1])
{
isPalindrome[i][i+1] = true;
maxLen = 2;
}
}
for(int l = 3; l < len; l++)
{
for(int i = 0; i <= len - l; i++)
{
int j = l+i-1;
if(s[i] == s[j] && isPalindrome[i+1][j-1])
{
isPalindrome[i][j] = true;
maxLen = l;
}
else
isPalindrome[i][j] = 0;
}
}
return maxLen;
}
3、中心扩展
{
int len = s.size();
int begin = c1, end = c2;
while(begin>=0 && end<=len-1 && s[begin]==s[end])
{
begin--;
end++;
}
return (end-begin-1); //end-begin+1-2
}
int FindLongestPalindrome3(string s)
{
int len = s.size();
int maxLen = 0;
for(int i = 0; i < len-1; i++)
{
int len1 = ExpandAroundCenter(s, i, i); //回文长度为奇数,aba
int len2 = ExpandAroundCenter(s, i, i+1); //回文长度为偶数,abba
int len = (len1 > len2)? len1:len2;
if(len > maxLen)
maxLen = len;
}
return maxLen;
}
4、Manacher法
{
string t;
for(int i = 0; i < s.size(); i++)
t += "#" + s.substr(i,1);
t += "#";
int len = t.size();
int *num = new int[len]();
int c = 0, r = 0;
for(int i = 0; i < len; i++)
{
int i_mirror = 2*c - i; //c-(i-c)
num[i] = (r > i)? (min(num[i_mirror], r-i)):0;
while(i+num[i]+1 <= len-1 && i-num[i]-1 >=0 && t[i+num[i]+1] == t[i-num[i]-1])
num[i]++;
if(i+num[i] > r)
{
r = i+num[i];
c = i;
}
}
int maxLen = 0;
for(int i = 0; i < len; i++)
{
if(num[i] > maxLen)
maxLen = num[i];
}
delete []num;
return maxLen;
}