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
  • 相关阅读:
    细说VMWare加入OpenStack
    云计算和大数据的崛起
    HTML5 Web app开发工具Kendo UI Web教程:如何配置Kendo UI Calendar
    Android:增强目录选择器对话框
    Gartner指明2014年几大战略技术趋势
    Android开发人员终于在“app-构建控制台”中获得分析
    谷歌升级Android分析应用程序
    Android是Windows开发人员可选择的下一个平台
    Greek
    为什么质数有无穷多个
  • 原文地址:https://www.cnblogs.com/tommychok/p/5304484.html
Copyright © 2011-2022 走看看