zoukankan      html  css  js  c++  java
  • HDU 1513 Palindrome:LCS(最长公共子序列)or 记忆化搜索

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513

    题意:

      给你一个字符串s,你可以在s中的任意位置添加任意字符,问你将s变成一个回文串最少需要添加字符的个数。

    题解1(LCS):

      很神奇的做法。

      先求s和s的反串的LCS,也就是原串中已经满足回文性质的字符个数。

      然后要变成回文串的话,只需要为剩下的每个落单的字符,相应地插入一个和它相同的字符即可。

      所以答案是:s.size()-LCS(s,rev(s))

      另外,求LCS时只会用到lcs[i-1][j-1],lcs[i-1][j],lcs[i][j-1],因为空间不够,改为滚动数组,将第一维[MAX_N]变为[2]。

    题解2(记忆化搜索):

      做法是对的,但是空间占用太大,会MLE。

      dfs(x,y)表示让s串中[x,y]这个区间变为回文串的花费。

      两种情况:

        (1)s[x]==s[y]:

            s[x]和s[y]已经配对,所以return dfs(x+1,y-1);

        (2)s[x]!=s[y]:

            有两种解决办法:

              1.让[x+1,y]变为回文串,然后在y的右边添加一个字符等于s[x]。

              2.让[x,y-1]变为回文串,然后在x的左边添加一个字符等于s[y]。

            所以return min(dfs(x+1,y),dfs(x,y-1))+1;

      判断dfs结束边界:

        (1)dp[x][y]!=-1:之前已经算过了,那就不用再算一遍了,return dp[x][y]。

        (2)x==y: return 0;

        (3)x+1==y: 如果s[x]==s[y],return 0;如果s[x]!=s[y],return 1;

      另外,每次dfs算出新的dp时,及时保存到dp数组中。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define MAX_N 5005
     6 
     7 using namespace std;
     8 
     9 int n;
    10 int dp[2][MAX_N];
    11 string s;
    12 
    13 int lcs(string a,string b)
    14 {
    15     memset(dp,0,sizeof(dp));
    16     for(int i=1;i<=a.size();i++)
    17     {
    18         for(int j=1;j<=b.size();j++)
    19         {
    20             if(a[i-1]==b[j-1]) dp[i&1][j]=dp[(i-1)&1][j-1]+1;
    21             else dp[i&1][j]=max(dp[(i-1)&1][j],dp[i&1][j-1]);
    22         }
    23     }
    24     return dp[a.size()&1][b.size()];
    25 }
    26 
    27 int palindrome(string s)
    28 {
    29     string rev=s;
    30     reverse(rev.begin(),rev.end());
    31     return s.size()-lcs(s,rev);
    32 }
    33 
    34 int main()
    35 {
    36     while(cin>>n>>s)
    37     {
    38         cout<<palindrome(s)<<endl;
    39     }
    40 }

    没AC Code:

     1 // dp[x][y] = min num of chars appended to s
     2 // dp[x][x] = 0
     3 //
     4 // 1) s[i] != s[j]:
     5 // dp[x][x+1] = 1
     6 // dp[x][y] = min(dp[x+1][y], dp[x][y-1]) + 1
     7 //
     8 // 2) s[i] == s[j]
     9 // dp[x][y] = dp[x+1][y-1]
    10 
    11 #include <iostream>
    12 #include <stdio.h>
    13 #include <string.h>
    14 #define MAX_N 5005
    15 
    16 using namespace std;
    17 
    18 int n;
    19 int dp[MAX_N][MAX_N];
    20 string s;
    21 
    22 int dfs(int x,int y)
    23 {
    24     if(dp[x][y]!=-1) return dp[x][y];
    25     if(x==y) return dp[x][y]=0;
    26     if(x+1==y) return dp[x][y]=(s[x]==s[y]?0:1);
    27     if(s[x]==s[y]) return dp[x][y]=dfs(x+1,y-1);
    28     return dp[x][y]=min(dfs(x+1,y),dfs(x,y-1))+1;
    29 }
    30 
    31 int main()
    32 {
    33     while(cin>>n>>s)
    34     {
    35         memset(dp,-1,sizeof(dp));
    36         cout<<dfs(0,s.size()-1)<<endl;
    37     }
    38 }
  • 相关阅读:
    Jeecg代码搬砖圣地第五篇(页面布局)
    Jeecg代码搬砖圣地第四篇(页面标签规则)
    Jeecg代码搬砖圣地第三篇(Excel导入导出)
    小程序前端
    javascript 新版本的语法(ECS6)
    nginx下用getallheaders
    wampser 配置debug需要的参数
    Suhosin(php的保护工具)
    php中empty使用的情况
    写出健壮的代码
  • 原文地址:https://www.cnblogs.com/Leohh/p/7376156.html
Copyright © 2011-2022 走看看