> 简洁易懂讲清原理,讲不清你来打我~

输入一个字符串,找到回文、子串、最长,输出任意一个子串
![在这里插入图片描述](https://img-blog.csdnimg.cn/d41d06c3dff44590ba833b0441e2b8c1.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/88e76956ddaf451fa72b1b8aff2d7a74.png)

> 暴力

明确i是子串长度,j是子串起点,i+j-1是子串终点,str1是子串,str2是翻转串,ans是回文、子串、最长

```cpp
class Solution {
public:
string longestPalindrome(string s) {
string ans="";
for(int i=1;i<=s.size();i++){
for(int j=0;i+j-1<s.size();j++){
string str1,str2;
str1=str2=s.substr(j,i);
reverse(str2.begin(),str2.end());
if(str1==str2)ans=(str1.size()>ans.size()?str1:ans);
}
}
return ans;

}
};
```

> 动态规划

明确dp1,3 表示s[1,3]是否为子串,len是子串长度,begin是子串起点,end=begin+len-1是子串终点,ans是回文、子串、最长,ans_begin、ans_len是回文、子串、最长的起点长度
len == 0,终点=起点;len == 1,终点=起点-1

```cpp
class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
//len==0、1直接输出
if(n<2)return s;
vector<vector<int>>dp(n,vector<int>(n));//dp[1,3]是s[1,3]是否是回文、子串
int ans_begin=0,ans_len=1;//回文、子串、最长的起点、长度
//len==0
for(int i=1;i<n;i++){
dp[i][i-1]=1;
}
//len==1
for(int i=0;i<n;i++){
dp[i][i]=1;
}
//len>=2
for(int len=2;len<=n;len++){
for(int begin=0;begin+len-1<n;begin++){
int end=begin+len-1;
//begin、end的字符不相等
if(s[begin]!=s[end])dp[begin][end]=0;
//begin、end的字符相等,扩展
if(s[begin]==s[end]){
dp[begin][end]=dp[begin+1][end-1];
}
if(dp[begin][end]&&len>ans_len)ans_len=len,ans_begin=begin;
}
}
return s.substr(ans_begin,ans_len);
}
};
```

> 中心扩展

简单的思路
从1个或2个字符左右扩展,

精准的定义
i、i+1是将要扩展的起点、终点
begin1、end1是从1个字符扩展结束后的起点、终点
begin2、end2是从2个字符扩展结束后的起点、终点
begin、end是子串起点、终点
ans_begin、ans_end是回文、子串、最长的起点、终点

```cpp
class Solution {
public:
string longestPalindrome(string s) {

int ans_begin=s.size()-1,ans_end=0;//ans_begin、ans_end是回文、子串、最长起点终点
//i、i+1是未扩展的回文子串起点终点
for(int i=0;i<s.size()-1;i++){
//begin1,end1是从1个字符扩展结束后的起点终点
auto [begin1,end1]=expand(s,i,i);
if(end1-begin1>ans_end-ans_begin)ans_begin=begin1,ans_end=end1;
//begin2、end2是从2个字符扩展结束后的起点终点
if(s[i]==s[i+1]){
auto [begin2,end2]=expand(s,i,i+1);
if(end2-begin2>ans_end-ans_begin)ans_begin=begin2,ans_end=end2;
}
}
return s.substr(ans_begin,ans_end-ans_begin+1);
}
pair<int,int> expand(const string &s,int begin,int end){
//begin,end是回文子串起点终点
while(begin-1>=0&&end+1<s.size()&&s[begin-1]==s[end+1]){
begin--,end++;
}
return {begin,end};
}
};
```

踩过的坑

> 马拉车算法

简单的思路
已知当前位置的臂长arm,下一个位置要扩展的时候可以利用前面的臂长

精准的定义

踩过的坑

 

 

 

1
> 喜欢简洁易懂还能讲清楚原理博客的小伙伴就关注关注这个非常高产的博主呀,下次再会~

posted on 2021-07-24 00:01  offer快到碗里来~  阅读(33)  评论(0)    收藏  举报