首页 > 其他分享 >dp-最长回文子序列

dp-最长回文子序列

时间:2023-08-13 16:46:10浏览次数:40  
标签:int 字符串 序列 include 最长 dp 回文

最长回文子序列

算法导论3rd - 15.2

问题描述

回文:palindrome,是正序和逆序完全相同的非空字符串

一个字符串有许多子序列,可以通过删除某些字符而变成回文字符串,字符串“cabbeaf”,删掉‘c’、'e'、‘f’后剩下的子串“abba”就是回文字符串,也是其中最长的回文子序列。在一个给定的字符串中,找到最长的回文子序列,并且返回这个子序列,这就是最长回文子序列LPS问题。注意和最长回文子串的区别,最长回文子串必须是连续的,这里的最长回文子序列,可以是不连续的。

思路

f(i...j) =
    f(i+1...j-1) + 1,               if s[i]==s[j]
    max(f(i+1...j), f(i...j-1)),    else

程序

// 最长回文子序列

#include <iostream>
#include <string>
#include <string.h>
#include <time.h>
#include <new>

using namespace std;

void solve();
template<typename T>
void print_mat(T** mat, int len1, int len2);


int main(int argc, char** argv) {
    clock_t start, end;
    start = clock();
    solve();
    end = clock();

    cout << "time cost: " << (end-start)*1000./CLOCKS_PER_SEC << " ms\n";


    return 0;
}


void solve() {
    //const char* str = "character";
    //const char* str = "mabcmcba";
    const char* str = "cabbeaf";
    int len = strlen(str);
    char* ret = new char[len + 1]{0};
    int** direct = new int*[len]{0};
    int** length = new int*[len]{0};
    for (int i = 0; i < len; ++i) {
        direct[i] = new int[len]{0};
        length[i] = new int[len];
        for (int j = 0; j < len; ++j) {
            length[i][j] = i==j? 1 : -1;
        }
    }

    for (int diff = 1; diff < len; ++diff) {
        for (int i = 0; i < len - diff; ++i) {
            int j = i + diff;
            if (str[i] == str[j]) {
                length[i][j] = (i <= j-2 ? length[i+1][j-1] : 0) + 2;
                direct[i][j] = 3;       // 3代表左侧和右侧都向内缩进
            } else {
                if (length[i+1][j] < length[i][j-1]) {
                    length[i][j] = length[i][j-1];
                    direct[i][j] = 2;   // 2 代表右侧向内缩进
                } else {
                    length[i][j] = length[i+1][j];
                    direct[i][j] = 1;   // 1 代表左侧向内缩进
                }
            }
        }
    }
    int l = length[0][len-1];

    cout << "direct:\n";
    print_mat(direct, len, len);
    cout << "length:\n";
    print_mat(length, len, len);
    cout << "l: " << l << endl;

    // 获取回文字符串
    int begin = 0, end = len-1, idx = 0;
    while (begin < end) {
        switch(direct[begin][end]) {
            case 3:
                ret[idx] = str[begin];
                ret[l-idx-1] = str[begin];
                ++begin;
                --end;
                ++idx;
                break;
            case 2:
                --end;
                break;
            case 1:
                ++begin;
                break;
        }
    }
    if (begin == end) {
        ret[idx] = str[begin];
    }
    cout << "ret: " << ret << endl;

    for (int i = 0; i < len; ++i) {
        delete[] direct[i];
        delete[] length[i];
    }
    delete[] direct;
    delete[] length;
    delete[] ret;
}

template<typename T>
void print_mat(T** mat, int len1, int len2) {
    for (int i = 0; i < len1; ++i) {
        for (int j = 0; j < len2; ++j) {
            cout << mat[i][j] << "\t";
        }
        cout << endl;
    }
}

测试:

direct:
0	1	1	1	1	1	1
0	0	1	1	1	3	2
0	0	0	3	2	2	2
0	0	0	0	1	1	1
0	0	0	0	0	1	1
0	0	0	0	0	0	1
0	0	0	0	0	0	0
length:
1	1	1	2	2	4	4
-1	1	1	2	2	4	4
-1	-1	1	2	2	2	2
-1	-1	-1	1	1	1	1
-1	-1	-1	-1	1	1	1
-1	-1	-1	-1	-1	1	1
-1	-1	-1	-1	-1	-1	1
l: 4
ret: abba
time cost: 0.141 ms

标签:int,字符串,序列,include,最长,dp,回文
From: https://www.cnblogs.com/minding/p/17626754.html

相关文章

  • dp-最长公共子序列
    最长公共子序列目录最长公共子序列问题描述最长公共子序列不等于最长公共子串问题分析程序问题描述最长公共子序列(LCS)是一个在一个序列集合中(通常为两个序列)用来查找所有序列中最长子序列的问题。一个数列,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的......
  • dp-最优二叉搜索树
    最优二叉搜索树目录最优二叉搜索树问题描述问题分析思路程序问题描述最优二叉搜索树(OptimalBinarySearchTree,OptimalBST)问题,形式化定义:给定一个n个不同关键字的已排序的序列K=<k1,k2,...,kn>(k1<k2<...<kn),用这些关键字构造一棵二叉搜索树——对每个关键字ki,都有一个概......
  • 无涯教程-Perl - readpipe函数
    描述该函数将EXPR作为命令执行。然后,将输出作为标量文本中的多行字符串返回,或者将行作为列表context中的单个元素返回。语法以下是此函数的简单语法-readpipeEXPR返回值此函数在标量context中返回String,在列表context中返回List。例以下是显示其基本用法的示例代码......
  • MATLAB用深度学习长短期记忆 (LSTM) 神经网络对智能手机传感器时间序列数据进行分类|
    最近我们被客户要求撰写关于长短期记忆(LSTM)神经网络的研究报告,包括一些图形和统计输出。此示例说明如何使用长短期记忆(LSTM)网络对序列数据的每个时间步长进行分类。要训练深度神经网络对序列数据的每个时间步进行分类,可以使用 序列对序列LSTM网络。序列对序列LSTM网络......
  • 斜率优化DP
    前置芝士单调队列优化DP⌈写不动数据结构呜呜呜,先来补这个⌋对于一个DP,我们想优化祂的⌈转移⌋有些题目的可选状态有以下特征需要寻找最值可选状态区间平移存在可以永久去除的多余状态感性的讲,可行性是一个滑动窗口,状态两两之间都可以⌈直接比较出优劣......
  • 最长公共子序列
    最长公共子序列题目描述给定长度为\(n\)的数组\(a\),长度为\(m\)的数组\(b\),求其最长公共子序列长度DP\(f[i][j]\)表示\(a\)前\(i\)项和\(b\)前\(j\)项的最长公共子序列长度因为如果我们要在序列尾巴上加元素是不跟前面选了什么有关系的,所以没有后效性,珂以DP......
  • 最长上升子序列
    最长上升子序列题目描述给定一个长度为\(n\)的数列\(a\),求其最长上升子序列长度DP\(O(n^2)\)\(f[i]\)表示以\(i\)结尾的最长上升子序列显然有\(f[i]=max(f[i],f[j]+1)\)其中\(1\leqi\leqn,1\leqj\leqi,f[0]=0,f[n]\)即为所求codefor(inti=1;i<=n;++i)......
  • UDP
    UDP不像TCP创建连接时有3次握手,而是直接发送数据,不管对方是否接收到。UDP网络通信不区分客户端和服务端。 UDP收发数据的步骤1.创建UDP套接字对象2.直接发送数据3.读取数据4.关闭套接字 示例服务端1'''2UDP应该说没有服务端和客户端,只是习惯称发......
  • [MDP.Net] 平台架構
    MDP.Net將應用系統切割為:模組、隔離、平台三個分層,透過架構設計提供模組重用、參數調整、環境建置...等等面向的快速開發能力。-模組:企業的商業知識、共用的功能邏輯,在MDP.Net裡會被開發成為一個一個的「模組」,方便開發人員依照商業需求,快速組合出應用系統。-隔離:MDP.Net加......
  • [MDP.Net] 模組架構
    MDP.Net遵循三層式架構,將模組開發切割為:系統展示、領域邏輯、資料存取三個分層,減少模組對於元件、平台、框架的直接依賴,提高模組自身的內聚力。-系統展示(Presentation):與目標客戶互動、與遠端系統通訊...等等的功能邏輯,會被歸類在系統展示。例如,使用MessageBox通知使用者處理......