zoukankan      html  css  js  c++  java
  • 动态规划-最长回文子串

    最长回文子串

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

    给出一个字符串 S,求 S 的最长回文子串的长度

    例子:

    字符串 "PATZJUJZTACCBCC" 的最长回文子串为 "ATZJUJZTA",长度为 9

    还是先看暴力解法,枚举子串的两个端点 i 和 j,需要判断在 [i, j] 内的子串是否回文,从复杂度上看,枚举端点需要 O(n2),判断回文需要 O(n),总复杂度为 O(n3)。

    那我们介绍一下动态规划下时间复杂度为O(n2) 的一种解法。

    dp[i][j] 为 S[i] 到 S[j] 是否为回文子串,是则为 1,否则为 0。这样根据 S[i] 是否等于 S[j] ,可以把情况分为两种:

    • 如果S[i] == s[j],那么只要 S[i+1] S[j-1]是回文子串,S[i]S[j] 就是回文子串;如果 S[i+1]至S[j-1] 不是回文子串,则 S[i]至S[j] 也不是回文子串
    • S[i] != S[j] ,那么 S[i]至S[j] 一定不是回文子串

    由此写出状态转移方程:

    if(S[i] == S[j]) dp[i][j] = dp[i+1][j-1]

    if(S[i] != S[j]) dp[i][j] = 0

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

    注意这个时候可能出现某些状态始终转移不到的情况,比如说我们 先固定 i, 然后 j 从 2 开始枚举

    • dp[0][2] => dp[1][1] 初始化过,能够求☑️
    • dp[0][3] => dp[1][2] 初始化过,能够求☑️
    • dp[0][4] => dp[1][3] 未初始化过,不能够求❌

    而且不论怎么转移都转移不到这个状态,所以我们必须想出新的枚举方式:

    • 根据递推写法从边界出发的原理,注意到边界表示的是长度为 1 和 2 的子串,且每次转移时都对子串长度减 1,因此不妨按照子串的长度和初始位置进行枚举!
    • 也就是第一遍把所有长度为 3 的子串枚举出来,第二次枚举长度为 4 的子串 ……

    先枚举长度 L (L可以取到字符串长度的),再枚举左端点 i,这样右端点 i + L -1 也能直接得到。

    代码实现:

    #include <cstdio>
    #include <cstring>
    
    const int maxn = 1010;
    char S[maxn];
    int dp[maxn][maxn];
    
    int main()
    {
      gets(S);
      int len = strlen(S), ans = 1;
      memset(dp, 0, sizeof(dp));
      // 边界
      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;
            ans = 2;	// 初始化时注意当前最长回文子串长度
          }
        }
      }
      // 状态转移方程
      for(int L = 3; L <= len; L++) {	// 枚举长度
        for(int i = 0; i + L - 1 < len; i++) {	// 枚举起始端点
          int j = i + L -1;	// 右端点
          if(S[i] == S[j] && dp[i+1][j-1] == 1) {
            dp[i][j] = 1;
            ans = L;	// 更新
          }
        }
      }
      printf("%d
    ", ans);
      return 0;
    }
    
    
  • 相关阅读:
    电脑设置开机
    python 环境搭建 python-3.4.4
    遍历hashmap 的四种方法
    Java8 使用 stream().map()提取List对象的某一列值及排重
    解决 SpringMVC 非spring管理的工具类使用@Autowired注解注入DAO为null的问题
    CXF之"@XmlType.name 和 @XmlType.namespace 为类分配不同的名称"错误
    java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSDL
    java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern
    java.lang.IllegalArgumentException: Request header is too large
    ie8 报错:意外地调用了方法或属性访问
  • 原文地址:https://www.cnblogs.com/veeupup/p/12548472.html
Copyright © 2011-2022 走看看