暴力破解应该是最好想到的,没什么思维难度,这里我就不赘述了。直接上代码。
class Solution {
public:
string longestPalindrome(string s) {
string res="";//存放结果
string temp="";//存放子串
for(int i=0;i<s.length();i++)
{
for(int j=i;j<s.length();j++)
{
temp=temp+s[j];
string tem=temp;//tem存放子串反转结果
std::reverse(tem.begin(),tem.end());//反转
if(temp==tem)
res=res.length()>temp.length()?res:temp;
}
temp="";
}
return res;
}
};
s[i~j]
(这表示字符串i~j
组成的字串)这一部分是回文串,并且j-i+1>2
,那么s[i+1~j-1]
也还是回文串。f[i][j]
表示字符串s
中从i
到j
组成的字串是否为字符串。我们用1
表示是,0
表示不是。j-i+1>2
):
s[i]=s[j]
,那么f[i][j]=f[i+1][j-1]
s[i]!=s[j[
,那么f[i][j]=0
f[i][i]=1
s[i]=s[i+1]
,那么它也是回文串,即f[i][i+1]=(s[i]==s[i+1])
f[i][j]=1
中,长度最长的那一个字串。class Solution {
public:
string longestPalindrome(string s)
{
int n = s.size();
if (n < 2) {
return s;
}
int maxLen = 1;
int begin = 0;
// dp[i][j] 表示 s[i..j] 是否是回文串
vector<vector<int>> dp(n, vector<int>(n));
// 初始化:所有长度为 1 的子串都是回文串
for (int i = 0; i < n; i++) {
dp[i][i] = true;
}
// 递推开始
// 先枚举子串长度
for (int L = 2; L <= n; L++)
{
// 枚举左边界,左边界的上限设置可以宽松一些
for (int i = 0; i < n; i++)
{
// 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
int j = L + i - 1;
// 如果右边界越界,就可以退出当前循环
if (j >= n)
break;
if (s[i] != s[j])
{
dp[i][j] = false;
}
else
{
if (j - i < 3)
{
dp[i][j] = true;
}
else
{
dp[i][j] = dp[i + 1][j - 1];
}
}
// 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
if (dp[i][j] && j - i + 1 > maxLen) {
maxLen = j - i + 1;
begin = i;
}
}
}
return s.substr(begin, maxLen);
}
};
debug
了半天 for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
}
}
maxlen
和begin
赋初始值,不然会被一些数据卡掉(比如s="ac"
)。我们知道每个回文串都会有回文中心,比如acbca
的回文中心就是b
,abccba
的回文中心就是cc
。那么我们就可以列举每一个回文中心,将它向外拓展,然后比较看哪个拓展的长度最长。
class Solution {
public:
pair<int,int> get(string &s,int l,int r) //一直向外拓展,获取以l,r为中心的最长回文串
{
while(l>=0 and r<s.length() and s[l]==s[r])
{
l--;
r++;
}
l++,r--;
return {l,r};
}
string longestPalindrome(string s)
{
int res=1,st=0; //记录最后的结果
for(int i=0;i<s.length();i++)
{
auto [l1,r1]=get(s,i,i); //第一种情况,回文中心为一个字符的
auto [l2,r2]=get(s,i,i+1); //第二次情况,回文中心为两个相邻字符的
if(res<r1-l1+1) //取最大值
{
res=r1-l1+1;
st=l1;
}
if(res<r2-l2+1)
{
res=r2-l2+1;
st=l2;
}
}
return s.substr(st,res);
}
};
由于这个算法太复杂,估计写出来也没什么人愿意看,我就不写了。其实我自己也没有搞明白
具体想了解的可以click here
如果你觉得我写题解还不错的,请各位王子公主移步到我的其他题解看看
- 数据结构与算法部分(还在更新中):
- C++ STL总结 - 基于算法竞赛(强力推荐)
- 动态规划——01背包问题
- 动态规划——完全背包问题
- 动态规划——多重背包问题
- 动态规划——分组背包问题
- 动态规划——最长上升子序列(LIS)
- 二叉树的中序遍历(三种方法)
- 最短路算法——Dijkstra(C++实现)
- 最短路算法———Bellman_Ford算法(C++实现)
- 最短路算法———SPFA算法(C++实现)
- 最小生成树算法———prim算法(C++实现)
- 最小生成树算法———Kruskal算法(C++实现)
- 染色法判断二分图(C++实现)
- Linux部分(还在更新中):
“种一颗树最好的是十年前,其次就是现在”
所以,
“让我们一起努力吧,去奔赴更高更远的山海”
如果有错误?,欢迎指正哟😋
🎉如果觉得收获满满,可以动动小手,点点赞👍,支持一下哟🎉