力扣刷题第4天——最长回文子串

一、题目概要

来源:力扣(LeetCode)
链接:
力扣

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

示例1:

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

示例2:

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

二、初始思路及代码

1、初始思路

使用类似第二题的滑动窗口解决->通过改变不同的启示位置依次尝试不同的字符串,与其逆转后的字符串对比,若二者相等则更新最大长度和最长回文,否则继续进行查找。

2、未通过的代码

class Solution {
public:
    string longestPalindrome(string s) { 
        int maxLength=0;
        string ans="";     
        for(int i=0;imaxLength){
                        maxLength=str.length();
                        ans=tempStr;
                    }
                }
                str=tempStr;
            }
        }
        return ans;
    }
};

3、错误分析

通过双重循环+逆转判断等操作增大了时间复杂度,导致运行超时未能通过。

三、正确答案

1、动态规划

1.1思路

设P(i,j)为存放是s[i]~s[j]是否为回文的判断结果的bool型变量,则会出现一个规律:当s[i:j](从s[i]到s[j])为回文时,s[i+1:j-1]也必定是回文,根据此规律可发现该问题存在递推关系。

此时有两个特殊情况:

①当s[i:j]的长度为1时,则该字符串必定是回文

②当s[i:j]的长度为2时,只要满足s[i]==s[i+1]则该字符串必定为回文

因此可以用情况②作为递推的底层,进而判断出所需结果。

1.2代码

class Solution {
public:
    string longestPalindrome(string s) { 
        int n=s.size();
        if(n<2){
            return s;
        }

        int maxLen=1,begin=0;
        vector>dp(n,vector(n));//用dp[i,j]存放从i到j的字符串是否为回文的判断结果
        for(int i=0;i=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];//递推
                    } 
                }
                if(dp[i][j]&&j-i+1>maxLen){
                    maxLen=j-i+1;
                    begin=i;
                }
            }
        }
        return s.substr(begin,maxLen);
    }
};

1.3代码分析

时间复杂度O(n^2)

空间复杂度O(n^2)

2中心扩展算法

2.1思路

核心思想与递推类似,依次选定字符串不同位置的s[i]作为中心点,依次向外扩展。根据上一解法可知,如果s[i:j]是回文,则s[i+1:j-1]必然是回文。因此该算法利用该特点向外扩展,直到扩展到的两个字符s[i]和s[j]不再相等后,返回两个下标i和j。

此外,扩展是会遇到两个不同情况:

①以奇数字符为中心,如bab的中心字符为a,是奇数字符,此时只需要从下标为1的位置直接向外扩展即可

②以偶数字符为中心,如baab的中心字符为aa,是偶数字符,此时则需要从i和i+1两个位置分别向外扩展

因此在书写外接函数时直接确定两个下标变量,若是情况①则传入i和i,若是情况②则传入i和i+1。

2.2代码

class Solution {
public:
    pairexpandAroundCenter(const string& s,int left,int right){
        while(left>=0&&right感觉类似递推
            left--;
            right++;
        }
        return {left+1,right-1};
    }

    string longestPalindrome(string s) { 
        int begin=0,end=0;
        for(int i=0;iend-begin){
                begin=left1;
                end=right1;
            }
            if(right2-left2>end-begin){
                begin=left2;
                end=right2;
            }
        }
        return s.substr(begin,end-begin+1);
    }
};

2.3代码分析

时间复杂度:O(n^2)

空间复杂度:O(1)

3、Manacher 算法(等后期有兴趣再补充)

四、每日打卡(滴滴!!)

2022.4.15 打卡完成!!!

你可能感兴趣的:(力扣,c++)