方法1:暴力判断所有子串:用两个for循环找出所有子串,第三个for循环用于判断该子串是否为回文,是回文则且比已找到的回文串长就替换,算法时间效率为O(n^3)
方法2:中心扩展法:遍历每个字符,以此为中心,往两边拓展,需要分为奇数回文和偶数回文两种情况:abcba 、abba。算法时间效率为O(n^2)
#include <iostream>
#include <vector>
#include <string>
#include <numeric>
#include<algorithm>
using namespace std;
int main()
{
string str;
while (cin >> str)
{
int size = str.size();
int max = 0;
int tmp(0);
for (auto i = 0; i < size; ++i)
{
//奇数回文
for (int j = 0; (i - j)>0 && (i + j) < size; ++j)
{
if (str[i - j] != str[i + j])
{
break;
}
tmp = 2 * j + 1;
}
if (tmp > max)
{
max = tmp;
}
//偶数回文
for (int j = 0; (i - j) >= 0 && (i + j + 1) < size;++j)
{
if (str[i - j] != str[i + j + 1])
{
break;
}
tmp = 2 * j+2;
}
if (tmp > max)
{
max = tmp;
}
}
cout << max << endl;
}
return 0;
}
- 方法3:动态规划
-动态规划:令f[i][j]表示以i开始,j结尾的回文串的长度:f[i][j]={0j−i+1str[i][j]不是回文串str[i][j]是回文串
则状态转移方程为:
f[i][j]=⎧⎩⎨0f[i+1][j−1]+2str[i]!=str[j]str[i]==str[j]
最长回文子串的长度为: max{f[i][j]}
注:回文子串是连续的,回文子序列是不连续的
#include <iostream>
#include <vector>
#include <string>
#include <numeric>
#include<algorithm>
using namespace std;
int main()
{
string str;
while (cin >> str)
{
int size = str.size();
vector<vector<int>> dp(size,vector<int>(size,0));
for (auto i = 0; i < size; ++i)
{
dp[i][i] = 1;
}
for (auto i = 0; i < size - 1; ++i)
{
dp[i][i + 1] = 0;
if (str[i] == str[i + 1])
{
dp[i][i + 1] = 2;
}
}
int max_(1);
int j;
for (auto len = 2; len < size; len++)
{
for (auto i = 0; i < size - len; ++i)
{
j = i + len;
if (str[i] == str[j])
{
dp[i][j] = dp[i+1][j-1] == 0 ? 0: dp[i + 1][j - 1] + 2;
max_ = max(max_, dp[i][j]);
}
else
{
dp[i][j] = 0;
}
}
}
cout << max_ << endl;
}
return 0;
}
- 方法4:Manacher算法
添加“#”,使abba变为a#b#b#a,将所有情况转化为奇数情况处理。