zoukankan      html  css  js  c++  java
  • POJ 1159 Palindrome

      POJ 1159

      题目大意:给定一个长度为n的字符串,求至少添加多少个字符能使得它变成回文串

      解题思路:求原串的逆串(abcdd的逆串为ddcba),然后求原串与逆串的最长公共子序列,即为c,则n-c即为最少添加的字符(不懂如何证明,只能大脑大概过明白)

           求两个字符串a,b的最长公共子序列:

             定义状态dp[i][j]表示a的前i个字符和b的前j个字符的最长公共子序列,那么dp[len1][len2]即为所求结果.

             初始状态: dp[i][0] = 0, dp[0][j] = 0, 对所有 i <= len1, j <= len2;

             状态转移方程: a[i] == b[j]时, dp[i][j] = dp[i-1][j-1]+1

                     a[i]  != b[j]时, dp[i][j] = MAX(dp[i-1][j], dp[i][j-1]);

             更加具体的状态转移方程推导请参考: HDU 1159题解

           另外由于此题n可以达到5000,因此开一个dp[5005][5005]的数组会超出内存,

           因此需采用一种叫做滚动数组的方式来节省空间。

           看状态转移方程,任何dp[i][j]的推导只使用到上一行的数组的状态,

           因此实际上开一个dp[2][5005],并把另一个当做当前需要更新的行的上一个状态即可。

           滚动数组有两种实现方式:

            一是将行进行取模: 如 dp[i%2][j] = dp[(i-1)%2][j]+1; (ai == bi时)

            二是定义一个变量e = 0,  每更新一行,就变换e,使e = 1 - e,即dp[e][j] = dp[1-e][j]+1; (ai == bj时)

    /* POJ 1159 Palindrome --- dp+滚动数组 */
    #include <cstdio>
    #include <cstring>
    
    const int N = 5005;
    int dp[2][N];
    char str1[N], str2[N];
    int n;
    
    inline int MAX(int a, int b){
        return a > b ? a : b;
    }
    
    int main()
    {
    #ifdef _LOCAL
        freopen("D:\input.txt", "r", stdin);
    #endif
        int n;
        //字符串长度为n
        while (scanf("%d", &n) == 1){
            scanf("%s", str1 + 1);
            //求逆串 
            for (int i = n; i > 0; --i){
                str2[n - i + 1] = str1[i];
            }
            int e = 0;
            memset(dp, 0, sizeof dp);
    
            //dp[i][j]表示子串的最大长度
            for (int i = 1; i <= n; ++i){
                e = 1 - e; //需要更新的行 即当前行 对应n*n中的 i
                for (int j = 1; j <= n; ++j){
                    if (str1[i] == str2[j]){
                        dp[e][j] = dp[1 - e][j - 1] + 1; //1-e对应i-1
                    }
                    else{
                        dp[e][j] = MAX(dp[1 - e][j], dp[e][j - 1]);
                    }
                }
            }
            printf("%d
    ", n - dp[e][n]);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    个人冲刺二(7)
    个人冲刺二(6)
    个人冲刺二(5)
    个人冲刺二(4)
    对称二叉树 · symmetric binary tree
    108 Convert Sorted Array to Binary Search Tree数组变成高度平衡的二叉树
    530.Minimum Absolute Difference in BST 二叉搜索树中的最小差的绝对值
    pp 集成工程师 mism师兄问一问
    17. Merge Two Binary Trees 融合二叉树
    270. Closest Binary Search Tree Value 二叉搜索树中,距离目标值最近的节点
  • 原文地址:https://www.cnblogs.com/tommychok/p/5304484.html
Copyright © 2011-2022 走看看