• UVa 10617 Again Palindrome(经典回文串区间DP)


    题意:

    给定一个字符串s,对s进行删除操作,使得剩下的子串是回文字符串,问最多有多少种这种子串。

    思路:

    涉及到回文字符串,首先要想到的肯定是区间DP,如何写出状态转移方程?

    直接从题意切入:dp[i, j]表示区间[i, j]最多有多少个这样的子串。

    1. s[i] == s[j] 去掉s[i],则一个子问题就是dp[i+1, j],去掉s[j],另一个子问题就是dp[i, j-1]。

       显然这两个子问题是会有重叠的,比如去掉s[i], s[j]的dp[i+1, j-1]。

       如果s[i],s[j]都不去掉呢?则这个子问题的解显然是dp[i+1, j-1] + 1。

       于是会有 dp[i][j] = dp[i+1][j] + dp[i][j-1] + 1;

    2. s[i] != s[j] 此时的子问题就比上述要简单了,因为s[i] s[j]与dp[i+1, j-1]的回文子串构成不了回文串。

       于是 dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1];

    总结:动态规划变化多端,不同的问题可能会有不同的切入点,一开始切入题目的时候可以采用最直接的按照题意来。

         无果之后再去思考一些见解的方法。这也算是渐进的一种方式了吧,首先不要试图把问题想的太复杂。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    
    #define max(a, b)    (((a) > (b)) ? (a) : (b))
    const int MAXN = 65;
    
    char str[MAXN];
    long long int dp[MAXN][MAXN];
    
    int main()
    {
        int cases;
        scanf("%d", &cases);
        while (cases--)
        {
            scanf("%s", str);
            int n = strlen(str);
    
            memset(dp, 0, sizeof(dp));
    
            for (int i = 0; i < n; ++i)
            {
                dp[i][i] = 1;
                if (str[i] == str[i+1])
                    dp[i][i+1] = 3;
                else
                    dp[i][i+1] = 2;
            }
    
            for (int p = 2; p < n; ++p)
            {
                for (int i = 0, j = p; j < n; ++i, ++j)
                    if (str[i] == str[j])
                        dp[i][j] = dp[i+1][j] + dp[i][j-1] + 1;
                    else
                        dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1];
            }
            printf("%lld\n", dp[0][n-1]);
        }
        return 0;
    }

     

    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    windows运行shell脚本
    Android Webview H5资源本地化
    Vscode开发Python环境安装
    Vscode开发Java环境搭建
    为什么索引可以提高效率?
    Java内存模型
    栈和队列----向有序的环形单链表中插入新节点
    栈和队列----单链表的选择排序
    栈和队列----将搜索二叉树转换成双向链表
    栈和队列----在单链表中删除指定值的节点
  • 原文地址:https://www.cnblogs.com/kedebug/p/2779296.html
Copyright © 2020-2023  润新知