zoukankan      html  css  js  c++  java
  • hdu 1513(滚动数组)

    Palindrome

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 4751    Accepted Submission(s): 1625


    Problem Description
    A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order to obtain a palindrome.

    As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.
     
    Input
    Your program is to read from standard input. The first line contains one integer: the length of the input string N, 3 <= N <= 5000. The second line contains one string with length N. The string is formed from uppercase letters from 'A' to 'Z', lowercase letters from 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercase letters are to be considered distinct.
     
    Output
    Your program is to write to standard output. The first line contains one integer, which is the desired minimal number.
     
    Sample Input
    5 Ab3bd
     
    Sample Output
    2
     
    Source
     
    这题用区间DP会爆内存。。正确解法利用LCS解,并且LCS算法算的时候只和当前行和上一行有关,所以利用滚动数组压缩空间
    ///题意:将一个字符串变成回文串需要添加的最少字符数量
    ///解法:将字符串反过来.求出原字符串与现在的字符串的LCS,然后用原串减掉LCS的长度即为最少添加的字符
    ///这个解法的好处就是可以将DP数组变成滚动数组
    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    const int N = 5001;
    int dp[2][N];
    char str[N],str1[N];
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF){
            scanf("%s",str+1);
            for(int i=1;i<=n;i++){
                str1[n-i+1]=str[i];
            }
            ///printf("%s",str1+1);
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(str[i]==str1[j]){
                        dp[i%2][j] = dp[(i-1)%2][j-1]+1;
                    }else{
                        dp[i%2][j] = max(dp[i%2][j-1],dp[(i-1)%2][j]);
                    }
                }
            }
            printf("%d
    ",n-max(dp[1][n],dp[0][n]));
        }
    }

    贴个爆内存的代码。。开short都没用,hdu数据强吗 ORZ ~~~

    ///题意:将一个字符串变成回文串需要添加的最少字符数量
    ///解法:区间DP,dp[i][j]代表区间i-j里面要添加多少个字符才能将其变成回文串
    ///如果 str[i] == str[j] 那么 dp[i][j] = dp[i+1][j-1]
    ///否则 dp[i][j] = min(dp[i+1][j] ,dp[i][j-1])+1 即考虑是在第i+1个字符之前添加str[j]还是在
    ///在j-1之后添加字符str[i]
    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    const int N = 5000;
    short dp[N][N];
    char str[N];
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF){
            scanf("%s",str);
            for(int i=1;i<=n;i++) dp[i][i]=0;///区间长度为1的时候不需要添加就是回文串
            for(int l = 2;l<=n;l++){
                for(int i=0;i<=n-l+1;i++){
                    int j = i+l-1;
                    if(str[i]==str[j]) {
                        dp[i][j] = dp[i+1][j-1];
                    }else{
                        dp[i][j] = min(dp[i+1][j],dp[i][j-1])+1;
                    }
                }
            }
            printf("%d
    ",dp[0][n-1]);
        }
    }
  • 相关阅读:
    光学镜头参数详解(EFL、TTL、BFL、FFL、FBL/FFL、FOV、F/NO、RI、MTF、TVLine、Flare/Ghost)
    三角函数公式
    技术工人的升华
    如何在apache启动的时候不输入ssl的密码
    汉字转拼音问题
    深入PHP内核(1) 引用
    如何把普通的exe服务器程序注册成windows 服务
    如何学习Yii
    横向同步问题
    多态的内幕(C++, C)语言两个版本
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5420600.html
Copyright © 2011-2022 走看看