题目如下:
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
我一共写了三种解法,分别是暴力搜索,动态规划和manacher算法(马拉车算法),时间分别为3180ms,1196ms和12ms,因此manacher算法在解这题的时候时间复杂度远远小于其他两种算法。这也是leetcode的优点吧,可以横向学习和比较各种算法,加深对各种复杂算法的理解。以下先放代码,具体解释以后再更新。
参考博文网址如下:
暴力搜索:
具体网址忘了,那个博主其实也就是给了思路,没给参考代码,大概意思就是选一个点,向两边伸展,对比元素是否对称,比较麻烦的地方是需要考虑对称串是奇数串还是偶数串的问题。
动态规划:
https://blog.csdn.net/shineboyxxb/article/details/52079360
manacher算法:
https://www.cnblogs.com/mini-coconut/p/9074315.html
https://www.cnblogs.com/love-yh/p/7072161.html
暴力搜索:
string longestPalindrome(string s) //暴力搜索
{
int length = 0;
string maxStr;
int totalSize = s.length();
for (int i = 0; i < totalSize; i++)
{
int lengthTemp1=0;
string temp1;
int lengthTemp2=0;
string temp2;
for (int j =0;; j++)
{
if ((i - j < 0) || (i + j > totalSize - 1))
{
break;
}
if (s[i - j] == s[i + j])
{
temp1 = s.substr(i - j, 2 * j + 1);
lengthTemp1 = 2 * j + 1;
}
else
{
break;
}
}
for (int j = 0;; j++)
{
if (i + 1>totalSize-1)
{
break;
}
if (s[i] == s[i + 1])
{
if (i - j<0 || i + 1 + j>totalSize - 1)
{
break;
}
if (s[i - j] == s[i + j + 1])
{
temp2 = s.substr(i - j, 2 * j + 2);
lengthTemp2 = 2 * j + 2;
}
else
{
break;
}
}
else
{
break;
}
}
if (lengthTemp1<lengthTemp2)
{
lengthTemp1 = lengthTemp2;
temp1 = temp2;
}
if (length < lengthTemp1)
{
length = lengthTemp1;
maxStr = temp1;
}
}
return maxStr;
}
动态规划:
string longestPalindrome(string s) //动态规划
{
int size = s.size();
vector<vector<bool>> dp(size,vector<bool>(size,false));
int start = 0;
int maxLength = 1;
for (int i = 0; i < size; i++)
{
for (int j = 0; j <=i; j++)
{
if (i - j < 2)
{
dp[j][i] = (s[j]==s[i]);
}
else if (i - j >= 2)
{
dp[j][i] = (s[j] == s[i]) && (dp[j+1][i-1]);
}
if (dp[j][i] && maxLength < i - j + 1)
{
maxLength = i - j + 1;
start = j;
}
}
}
return s.substr(start,maxLength);
}
manacher算法:
string longestPalindrome(string s) //manacher算法
{
string newStr = "$#";
for (int i = 0; i < s.length(); i++)
{
newStr += s[i];
newStr += "#";
}
vector<int> Len(newStr.length(), 0);
int pos = 0, mx = 0;
int start = 0, maxLen = 0;
for (int i = 1; i < newStr.size(); i++)
{
Len[i] = i < mx ? min(Len[2 * pos - i], mx - i) : 1;
while (i + Len[i] < newStr.size() && i - Len[i]>0 && newStr[i + Len[i]] == newStr[i - Len[i]])
Len[i]++;
if (i + Len[i] > mx) //如果新计算的最右侧端点大于mx,则更新pos和mx
{
pos = i;
mx = i + Len[i];
}
if (Len[i] - 1 > maxLen)
{
start = (i - Len[i]) / 2;
maxLen = Len[i] - 1;
}
}
return s.substr(start, maxLen);
}