首页 > 试题广场 >

手写代码:查找最长回文子串

[问答题]

手写代码:查找最长回文子串

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

    }
};
发表于 2022-06-14 10:22:01 回复(0)
最长回文子串
令dp[i][j]表示s[i]到s[j]所表示的子串是否是回文子串,是则为1,不是为0,这样根据s[i]是否等于s[j],可以分为两种情况:
1)若s[i]=s[j],那么只要s[i+1]至s[j-1]是回文子串,s[i]至s[j]就是回文子串,如果 要s[i+1]至s[j-1]不是回文子串,那么s[i]至s[j]就不是回文子串。
2)如s[i]!=s[j],那么s[i]至s[j]一定不是回文子串
综上,状态方程:
dp[i][j] = dp[i+1][j-1];      //s[i]=s[j]
dp[i][j] = 0;      //s[i]!=s[j]
边界:dp[i][i]=1,dp[i][i+1] = (s[i] == s[i+1] ? 1 : 0)
按子串的长度和子串的初始位置进行枚举,即第一遍将长度为3的子串的dp值全部求出,第二遍通过第一遍结果计算出长度为4的子串的dp值....
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 1010;
int dp[MAXN][MAXN];


int main()
{
    string str; 
    cin >> str;
    int len = str.length();
    int maxLen = 1; //最长回文字子串的长度 
    memset(dp, 0, sizeof(dp)); //dp数组初始化为0
    //边界
    for(int i = 0; i < len; i++){
        dp[i][i] = 1;
        if(i < len - 1){
            if(str[i] == str[i + 1]){ //如果str[i] = str[i+1],则更新maxLen 
                dp[i][i + 1] = 1; 
                maxLen = 2;
            }
        }
    } 

    //状态转移方程
    for(int L = 3; L <= len; L++){ //枚举子串的长度,从3开始,因为上面的语句已经把长度为1和2的子串都枚举完毕
        for(int j = 0; j + L - 1 < len; j++){ //枚举子串的起点 
            int i = j + L - 1; //子串的右端点 
            if(str[j] == str[i] && dp[j + 1][i - 1] == 1){
                dp[j][i] = 1;
                maxLen = L; //更新maxLen 
            } 
        } 
    } 
    printf("%d", maxLen);
    return 0;
}


编辑于 2020-05-16 17:40:07 回复(0)