zoukankan      html  css  js  c++  java
  • Light OJ 1025

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1025

    题目大意:一串字符, 通过删除其中一些字符, 能够使这串字符变成回文串。 现在给你一串字符,问能够得到多少种不同的回文串;

    注意:字符串"abba", 可以得到9串回文串,分别为'a', 'a', 'b', 'b', 'aa', 'bb', 'aba', 'aba', 'abba'.

    解题思路:声明dp[i][j]为字符串[i,j]区间中通过删除可以得到不同回文串的数量

    那么有以下两种情况:

    1:当str[i] != str[j]时, dp[i][j] = dp[i][j-1] + dp[i+1][j] - dp[i+1][j-1]; (之所以减去dp[i+1][j-1] 是前面两项多加了一个dp[i+1][j-1])

    2:当str[i] == str[j]时, dp[i][j] = (dp[i][j-1] + dp[i+1][j] - dp[i+1][j-1]) + (dp[i+1][j-1] + 1);(前面一项是指str[i]和str[j]不对应时能够组成回文串的方案数,第二项是指str[i]和str[j]对应时能够组成回文串的方案数)

    需要注意的不能第一项直接循环i, 第二项直接循环j, 那么求dp[i][j]时,dp[i+1][j] 可能还没求得正确的值。

    dp数组代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int N = 103;
    ll dp[N][N];
    char str[N];
    void solve(int cases)
    {
        scanf("%s", str);
        int l = strlen(str);
        memset(dp, 0, sizeof(dp));
        for(int i=0; str[i]; ++ i)
            dp[i][i] = 1;
        for(int len=1; len<l; ++ len)
        {
            for(int i=0; i+len<l; ++ i)
            {
                int j=i+len;
                if(str[i] != str[j])
                    dp[i][j] = dp[i][j-1] + dp[i+1][j] - dp[i+1][j-1];
                else
                    dp[i][j] = dp[i][j-1] + dp[i+1][j] + 1;
            }
        }
        printf("Case %d: %lld
    ", cases, dp[0][l-1]);
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        for(int i=1; i<=T; ++ i)
            solve(i);
        return 0;
    }
    View Code

    记忆化搜索代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int N = 103;
    ll dp[N][N];
    char str[N];
    
    ll dfs(int l, int r)
    {
        if(l == r)
            return dp[l][r] = 1;
        if(dp[l][r] != -1)
            return dp[l][r];
        if(l > r)
            return 0;
    
        ll ans;
        if(str[l] != str[r])
            ans = dfs(l, r-1) + dfs(l+1, r) - dfs(l+1, r-1);
        else
            ans = dfs(l, r-1) + dfs(l+1, r) + 1;
    
        return dp[l][r] = ans;
    }
    
    void solve(int cases)
    {
        scanf("%s", str);
        int l = strlen(str);
        memset(dp, -1, sizeof(dp));
        printf("Case %d: %lld
    ", cases, dfs(0,l-1));
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        for(int i=1; i<=T; ++ i)
            solve(i);
        return 0;
    }
    View Code
  • 相关阅读:
    jekyll+livereload+chrome插件-更新文件后自动刷新
    boostraps+jekyll+sass/scss+less+grunt整合使用详细备忘
    Centos使用keepalived配置MySQL双主热备集群
    MySQL数据库的集群方案
    Nginx使用Lua脚本加解密RSA字符串
    Nginx使用Lua脚本连接Redis验证身份并下载文件
    Centos安装ELK
    Centos7中搭建Redis6集群操作步骤
    only-office以Docker方式安装使用
    Kafka笔记
  • 原文地址:https://www.cnblogs.com/aiterator/p/5875206.html
Copyright © 2011-2022 走看看