力扣5. 最长回文子串(双指针、dp)

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

 

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

 

示例 2:

输入:s = "cbbd"
输出:"bb"

 

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

 

该题的状态转移比较好想到,难点在于如何去填充dp数组。以往dp数组都是一行一行的更新,但在这道题中,dp[i][j]可能用到的是dp[i+1][j-1]的状态,而dp[i+1][j-1]这个状态要在下一层才会被更新,也就是说不能以行为单位进行更新,得以另外一种形式(也不是单纯的以列为单位)进行更新,具体的形式是外层循环控制右边界,内层循环控制左边界。当然,该题还有其他动态规划的解法。

 1 class Solution {
 2     bool dp[1005][1005]; //dp[i][j]表示字符串S(i,j)的是否为回文子串
 3 public:
 4     bool judge(string s){
 5         int head=0,tail=s.size()-1;
 6         while(head<=tail){
 7             if (s[head]!=s[tail])
 8                 return false;
 9             head++;
10             tail--;
11         }
12         return true;
13     }
14     string longestPalindrome(string s) {
15         memset(dp,false,sizeof(dp));
16         int max_head=0;  //最大子串的首字符
17         int mmax=1;  //最大子串长度
18         for (int r=1;r<s.size();++r){  //l表示左边界,r表示右边界
19             for (int l=0;l<r;++l){
20                 if (s[l]!=s[r]){  //字符串S(i,j)的两端相等才进一步判断是否为回文串
21                     continue;
22                 }else{
23                     if ((r-1)-(l+1)+1<=1){  //若字符串S(l+1,r-1)的长度为0或1,则直接是回文
24                         dp[l][r]=true;
25                     }else{  //状态转移
26                         dp[l][r]=dp[l+1][r-1];
27                     }
28                     if (dp[l][r]&&r-l+1>mmax){  //更新最大子串信息
29                         max_head=l;
30                         mmax=r-l+1;
31                     }                
32                 }
33             }
34         }
35         return s.substr(max_head,mmax);
36     }
37 };

 双指针法:主要考虑到回文串奇数与偶数时的不同,奇数的字符串中心是单字符,偶数的字符串中心是两个相同字符。

 1 class Solution {
 2 public:
 3     string findPalindrome(int i, int j, string s){
 4         while(i >= 0 && j < s.size() && s[i] == s[j]) {
 5             i--;
 6             j++;
 7         }
 8         return s.substr(i + 1, j - i - 1);
 9     }
10     string longestPalindrome(string s) {
11         string res = "";
12         for (int i = 0; i < s.size(); ++i) {
13             // 假设回文串为奇数长度,则以s[i]为中心
14             string temp = findPalindrome(i, i, s);
15             res = res.size() < temp.size() ? temp:res;
16             // 假设回文串为偶数长度,则以s[i]和s[i+1]为中心
17             temp = findPalindrome(i, i + 1, s);
18             res = res.size() < temp.size() ? temp:res;
19         }
20         return res;
21     }
22 };

 

posted on 2023-06-07 14:59  Coder何  阅读(35)  评论(0)    收藏  举报