力扣 5. 最长回文子串 dp 马拉车算法

https://leetcode-cn.com/problems/longest-palindromic-substring/在这里插入图片描述
思路一: d p dp dp,如果 s [ i … j ] s[i…j] s[ij]是回文串,那么 d p [ i ] [ j ] = 1 dp[i][j]=1 dp[i][j]=1,否则 d p [ i ] [ j ] = 0 dp[i][j]=0 dp[i][j]=0,显然 d p [ i ] [ i ] = 1 dp[i][i]=1 dp[i][i]=1,接下来枚举区间长度 l e n len len和起始点 i i i,那么终止点就是 j = i + l e n − 1 j=i+len-1 j=i+len1,只要 s [ i ] = s [ j ] s[i]=s[j] s[i]=s[j] d p [ i + 1 ] [ j − 1 ] = 1 dp[i+1][j-1]=1 dp[i+1][j1]=1就说明 s [ i … j ] s[i…j] s[ij]是回文串,复杂度 O ( n 2 ) O(n^2) O(n2)

class Solution {
    
    
public:
    string longestPalindrome(string s) {
    
    
        int n=s.size();
        vector<vector<bool>> dp(n,vector<bool>(n));
        int start=0,maxlen=1;
        dp[0][0]=1;
        for(int i=1;i<n;i++)
        {
    
    
            dp[i][i]=1;
            if(s[i]==s[i-1])
            {
    
    
                dp[i-1][i]=1;
                start=i-1;
                maxlen=2;
            }
        }
        for(int len=3;len<=n;len++)
        {
    
    
            for(int i=0;i+len-1<n;i++)
            {
    
    
                int j=i+len-1;
                if(s[i]==s[j]&&dp[i+1][j-1])
                {
    
    
                    dp[i][j]=1;
                    if(j-i+1>maxlen)
                        maxlen=j-i+1,start=i;
                }
            }
        }
        return s.substr(start,maxlen);
    }
};

思路二:考虑回文串的性质,我们可以从中间点向两边扩展从而判断一个字符串是否是回文串,那么对于长度为 n n n的字符串来说,其中间点一共有 2 ∗ n − 1 2*n-1 2n1种选择,具体一点: 1. 1. 1.以某个字符作为中心,这有 n n n种选择; 2. 2. 2.以相邻两个字符的中间作为中心,这有 n − 1 n-1 n1种选择。枚举即可,复杂度 O ( n 2 ) O(n^2) O(n2)

class Solution {
    
    
public:
    string longestPalindrome(string s) {
    
    
        int n=s.size();
        int start=0,maxlen=1;
        for(int i=0;i<n;i++)
        {
    
    
            int tmp=calLen(s,i,i);
            if(tmp>maxlen)
                maxlen=tmp,start=i-(tmp>>1);
            tmp=calLen(s,i,i+1);
            if(tmp>maxlen)
                maxlen=tmp,start=i-(tmp>>1)+1;
        }
        return s.substr(start,maxlen);
    }

    int calLen(const string &s,int l,int r)
    {
    
    
        int ml=0,mr=s.size()-1;
        while(l>=ml&&r<=mr&&s[l]==s[r])
            --l,++r;
        return r-l-1;
    }
};

思路三:马拉车算法,参见文章

class Solution {
    
    
public:
    string longestPalindrome(string s) {
    
    
        string t="#";
        int n=s.size();
        for(int i=0;i<n;i++)
        {
    
    
            t+=s[i];
            t+="#";
        }
        n<<=1;
        vector<int> len(n+1);
        int l=0,r=-1,k;
        int start=0,maxlen=1;
        for(int i=0;i<=n;i++)
        {
    
    
            k=i>=r?1:min(len[l+r-i],r-i);
            while(0<=i-k&&i+k<=n&&t[i-k]==t[i+k])
                ++k;
            len[i]=--k;
            if(i+k>r)
                l=i-k,r=i+k;
            if(len[i]>maxlen)
            {
    
    
                maxlen=len[i];
                start=(i-maxlen)>>1;
            }
        }
        return s.substr(start,maxlen);
    }
};

猜你喜欢

转载自blog.csdn.net/xiji333/article/details/114484210