zoukankan      html  css  js  c++  java
  • COJ559 回文

    试题描述
    给定字符串,求它的回文子序列个数。回文子序列反转字符顺序后仍然与原序列相同。
    例如字符串aba中,回文子序列为"a", "a", "aa", "b", "aba",共5个。
    注意:内容相同位置不同的子序列算不同的子序列。
    输入
    第一行一个整数T,表示数据组数。
    之后是T组数据,每组数据为一行字符串。
    输出
    对于每组数据输出一行,格式为"Case #X: Y",X代表数据编号(从1开始),Y为答案。答案对100007取模。
    输入示例
    5
    aba
    abcbaddabcba
    12111112351121
    ccccccc
    fdadfa
    输出示例
    Case #1: 5
    Case #2: 277
    Case #3: 1333
    Case #4: 127
    Case #5: 17
    其他说明
    1 ≤ T ≤ 10
    字符串长度 ≤ 1000

    第一眼hash、sa、马拉车什么的就行了。

    第二眼样例的答案怎么这么大?

    第三眼发现子串可以不连续

    第四眼发现N这么小

    第五眼发现这是一道裸的DP

    第六眼设计出状态f[i][j]表示[i,j]的回文子串数目

    第七眼设计出转移

    f[i][i]=1

    当s[i]!=s[j]时,根据容斥原理f[i][j]=f[i+1][j]+f[i][j-1]-f[i-1][j-1]

    当s[i]==s[j]时,答案还要加上f[i-1][j-1]+1即s[i]加入回文串首,s[j]加入回文串尾,即f[i][j]=f[i+1][j]+f[i][j-1]+1

    记忆化搜索有些慢(203ms)

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(s,t) for(int i=s;i<=t;i++)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=1010,mod=100007;
    int f[maxn][maxn];
    char s[maxn];
    int dp(int l,int r) {
        int& ans=f[l][r];
        if(l>=r) return !(l>r);
        if(ans) return ans;
        if(s[l]!=s[r]) return ans=(dp(l+1,r)+dp(l,r-1)-dp(l+1,r-1)+mod)%mod;
        return ans=(dp(l+1,r)+dp(l,r-1)+1)%mod;
    }
    int main() {
        int T=read();
        rep(1,T) {
            scanf("%s",s+1);
            int n=strlen(s+1);
            memset(f,0,sizeof(f));
            printf("Case #%d: %d
    ",i,dp(1,n));          
        }
        return 0;
    }
    View Code

    递推的话要以右端点升序,左端点降序来进行(79ms)

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(s,t) for(int i=s;i<=t;i++)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=1010,mod=100007;
    int f[maxn][maxn];
    char s[maxn];
    int main() {
        int T=read();
        rep(1,T) {
            scanf("%s",s+1);
            int n=strlen(s+1);
            for(int j=1;j<=n;j++) {
                f[j][j]=1;
                for(int i=j-1;i;i--) 
                    if(s[i]==s[j]) f[i][j]=(f[i+1][j]+f[i][j-1]+1)%mod;
                    else f[i][j]=(f[i+1][j]+f[i][j-1]-f[i+1][j-1]+mod)%mod;
            }
            printf("Case #%d: %d
    ",i,f[1][n]);          
        }
        return 0;
    }
    View Code
  • 相关阅读:
    jeecg+activemq之AjaxServlet+tomcat7
    odoo8.0 win7 64位 安装配置(补遗)
    odoo种种
    MySQL种种
    html种种
    jQuery种种
    freemarker种种
    jQuery ui autocomplete 与easyUI冲突解决办法(重命名ui的autocomplete 和menu部分)
    vue实现点击按钮下载图片
    VUE父子组件之间的传值,以及兄弟组件之间的传值
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4604071.html
Copyright © 2011-2022 走看看