最长回文子序列和最长回文子串

断了今生、忘了曾经 提交于 2021-02-18 17:33:07

对于回文子序列,因为是不连续的肯定是不能直接枚举,那么利用动态规划。

我们可以知道对于任意字符串,如果头尾字符相同,那么字符串的最长子序列等于去掉首尾的字符串的最长子序列加上首尾;如果首尾字符不同,则最长子序列等于去掉头的字符串的最长子序列和去掉尾的字符串的最长子序列的较大者。那么转移方程:dp[i][j]=dp[i+1][j-1] + 2  if(s[i] == s[j])

 dp[i][j]=max(dp[i+1][j],dp[i][j-1])  if (s[i] != s[j])

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1005;
char s[maxn];
int dp[maxn][maxn];
int main()
{
    scanf("%s",s);
    int len=strlen(s);
    for(int i=len-1;i>=0;i--)
    {
        dp[i][i]=1;
        for(int j=i+1;j<=len;j++)
        {
            if(s[i]==s[j])
                dp[i][j]=dp[i+1][j-1]+2;
            else
                dp[i][j]=max(dp[i][j-1],dp[i+1][j]);
        }
    }
    printf("%d\n",dp[0][len-1]);
    return 0;
}

最长回文子串的话,解决的方案比较多,我们还是利用动态规划去求解:

string longestPalindrome(string s)
{
    if (s.empty()) return "";
    int len = s.size();
    if (len == 1)return s;
    int longest = 1;
    int start=0;
    vector<vector<int> > dp(len,vector<int>(len));
    for (int i = 0; i < len; i++)
    {
        dp[i][i] = 1;
        if(i<len-1)
        {
            if (s[i] == s[i + 1])
            {
                dp[i][i + 1] = 1;
                start=i;
                longest=2;
            }
        }
    }
    for (int l = 3; l <= len; l++)//子串长度
    {
        for (int i = 0; i+l-1 < len; i++)//枚举子串的起始点
        {
            int j=l+i-1;//终点
            if (s[i] == s[j] && dp[i+1][j-1]==1)
            {
                dp[i][j] = 1;
                start=i;
                longest = l;
            }
        }
    }
    return s.substr(start,longest);
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!