zoukankan      html  css  js  c++  java
  • poj1159 Palindrome 区间DP

    题目链接:http://poj.org/problem?id=1159

    思路1:

    区间DP思想:

    定义dp[i][j]表示从区间(i,j)之间需要增加的字符的最少数量,那么如果s[i]==s[j],那么dp[i][j]=dp[i-1][j-1]

    否则dp[i][j]=min(dp[i+1][j]+1,dp[i][j-1]+1);

    如果直接DP,需要开5001*5001的数组,用int会超内存

    用short int 能过;

    代码如下:

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<string>
     6 using namespace std;
     7 short int  dp[5001][5001];
     8 string s;
     9 int main()
    10 {
    11         int n;
    12         while(scanf("%d",&n)!=EOF)
    13         {
    14                 memset(dp,0,sizeof(dp));
    15                cin>>s;
    16                for(int j=0;j<n;j++)
    17                        for(int i=j-1;i>=0;i--)
    18                                if(s[i]==s[j])
    19                                {
    20                                  dp[i][j]=dp[i+1][j-1];
    21                                }
    22                                else
    23                                {
    24                                  dp[i][j]=min(dp[i][j-1]+1,dp[i+1][j]+1);
    25                                }
    26                cout<<dp[0][n-1]<<endl;
    27         }
    28         return 0;
    29 }
    View Code

    但是定义short int 不是常规的做法;

    常规思路:LCS+滚动数组

    思路:

    很容易想到需要增加的字符长度等于字符串s的长度-字符串s与它的逆串s'的最长公共字串的长度

    然后问题就转化为LCS问题,简单吧

    只要在处理时用滚动数组将空间消耗从n*n降为n

    至于滚动数组,我们很容易知道dp[i]与dp[i-2]无关,所以只要开个2*n的空间即可,具体见代码:

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 int dp[2][5010];
     7 char s1[5010];
     8 char s2[5010];
     9 int main()
    10 {
    11        int n;
    12        while(scanf("%d",&n)!=EOF)
    13        {
    14                memset(dp,0,sizeof(dp));
    15                cin>>s1;
    16                 int j=0;
    17                for(int i=n-1; i >= 0; i--) 
    18                s2[j++] = s1[i];
    19                for(int i=0;i<n;i++)
    20                        for(int j=0;j<n;j++)
    21                               if(s1[i]==s2[j])
    22                                       dp[(i+1)%2][j+1]=dp[i%2][j]+1;
    23                                       else dp[(i+1)%2][j+1]=max(dp[(i+1)%2][j],dp[i%2][j+1]);
    24                cout<<n-dp[n%2][n]<<endl;
    25 
    26 
    27        }
    28        return 0;
    29 }
    View Code

  • 相关阅读:
    二 、异常
    Java的基本概念
    Oracle case when
    oracle exists
    一 、前言
    location
    HTTP1.1初识
    数学学习笔记(持续更新中)
    [NOIP2017 提高组] 列队 题解
    [NOI2019] 回家路线 题解
  • 原文地址:https://www.cnblogs.com/xiaozhuyang/p/poj1159.html
Copyright © 2011-2022 走看看