动态规划——最长回文子串

  最长回文子串的问题描述:

  下面介绍动态规划的方法,使用动态规划可以达到最优的 O(n2) 复杂度。

  令 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]=\left\{\begin{matrix}dp[i+1][j-1],S[i]==S[j]\\ 0,S[i]!=S[j]\end{matrix}\right.$

  边界:dp[i][i]=1,dp[i][i+1] = (S[i] == S[i+1]) ? 1 : 0。

  根据递推写法从边界出发的原理,注意到边界表示的是长度为 1 和 2 的子串,且每次转移时都对子串的长度减了 1,因此不妨考虑按子串的长度和子串的初始位置进行枚举,即第一遍将长度为 3 的子串的 dp 值全部求出,第二遍通过第一遍结果计算出长度为 4 的子串的 dp 值 ……

  代码如下:

 1 /*
 2     最长回文子串
 3 */
 4
 5 #include <stdio.h>
 6 #include <string.h>
 7 #include <math.h>
 8 #include <stdlib.h>
 9 #include <time.h>
10 #include <stdbool.h>
11
12 #define maxn 1010
13 char S[maxn];
14 int dp[maxn][maxn];
15
16 int main() {
17     gets(S);                        // 输入整行字符
18     int len=strlen(S), ans=1;        // ans 记录最长回文子串长度
19     int i, j, L;
20     // 边界
21     for(i=0; i<len; ++i) {
22         dp[i][i] = 1;
23         if(i < len-1) {
24             if(S[i] == S[i+1]) {
25                 dp[i][i+1] = 1;
26                 ans = 2;
27             }
28         }
29     }
30     // 状态转移方程
31     for(L=3; L<=len; ++L) {            // 枚举子串长度
32         for(i=0; i+L-1 < len; ++i) {    // 枚举子串的起始节点
33             j = i+L-1;                // 子串的右端结点
34             if(S[i]==S[j] && dp[i+1][j-1]==1) {
35                 dp[i][j] = 1;
36                 ans = L;            // 更新最长回文子串长度
37             }
38         }
39     }
40     printf("%d\n", ans);            // 输出
41
42     return 0;
43 }

原文地址:https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes30.html

时间: 2024-10-08 01:19:34

动态规划——最长回文子串的相关文章

[动态规划]最长回文子串

问题描述: 求一个字符串的最长回文子串,返回这个子串. 这个题目适合用动态规划的方式求解: 代码实现: string longestPalindrome(string s) { int size = s.size(); int dp[1000][1000] = {0}; int left = 0; int right = 0; int len = 0; for(int j = 0; j < size; ++j) { for(int i = 0; i < j; ++i) { if(j - i &

【数据结构与算法】动态规划——最长回文子串

最长回文子串 LeetCode:最长回文子串 题目描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案. 思想: 动态规划,用boolean[][] dp记录每一对字符是否相等: 双循环遍历所有子串情况,每次遍历时,当前子串首尾相等且内层-1字符串dp值为true,则记录dp值为true:全部遍历完,取最长,即为最

动态规划—最长回文子串LEETCODE第5题深度剖析

动态规划对于笔者来说有很重要的意义 一.题目如下: 对于此类题目,笔者常用的的办法是先做个暴力解题思路,然后再对暴力法进行优化. 二.暴力法 //字串遍历 public static String longestPalindrome(String s) { String result=""; if(s.length()==1) return s; for(int i=0;i<s.length();i++) { for(int j=i+1;j<s.length()+1;j++

动态规划 | 最长回文子串 1040

部分正确(19分)代码: #include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm>

Leetcode-最长回文子串(包含动态规划以及Manacher算法)

原文地址: https://www.cnblogs.com/mini-coconut/p/9074315.html 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案. 示例 2: 输入: "cbbd" 输出: "bb" 自己的思路:求一个字符串的最长回文子串,我们可以将以每个字符

leetcode-5 最长回文子串(动态规划)

题目要求: * 给定字符串,求解最长回文子串 * 字符串最长为1000 * 存在独一无二的最长回文字符串 求解思路: * 回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文字符串, * 那么P[i+1,j-1]也是回文字符串.这样最长回文子串就能分解成一系列子问题了. * 这样需要额外的空间O(N^2),算法复杂度也是O(N^2). * 首先定义状态方程和转移方程: * P[i,j]=0表示子串[i,j]不是回文串.P[i,j]=1表示子串[i,j]是回文串. * P

[C++]LeetCode: 99 Longest Palindromic Substring (最长回文子串)

题目:Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 思路:题目要求的s的一个最长回文子串.暴力解决办法就是枚举所有的子串,再对每个子串进行回文判断.进行剪枝,我们考虑可以使用动态规划来避免重复的判

(算法)最长回文子串

题目: 求一个字符串的最长回文子串 思路: 1.暴力枚举 最容易想到的就是暴力破解,列举每一个子串,然后根据回文的定义判断是不是回文,找到最长的那个. 求每一个子串的时间复杂度为O(N^2),判断子串是不是回文的时间复杂度为O(N),所以时间复杂度为O(N^3). 2.动态规划 回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文字符串,那么P[i+1,j-1]也是回文字符串.这样最长回文子串就能分解成一系列子问题了. 这样需要额外的空间是O(N^2),时间复杂度也是O

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和

参考:http://www.ahathinking.com/archives/124.html 最长公共子序列 1.动态规划解决过程 1)描述一个最长公共子序列 如果序列比较短,可以采用蛮力法枚举出X的所有子序列,然后检查是否是Y的子序列,并记录所发现的最长子序列.如果序列比较长,这种方法需要指数级时间,不切实际. LCS的最优子结构定理:设X={x1,x2,……,xm}和Y={y1,y2,……,yn}为两个序列,并设Z={z1.z2.……,zk}为X和Y的任意一个LCS,则: (1)如果xm=