zoukankan      html  css  js  c++  java
  • cdqz2017-test10-加帕里图书馆(区间DP & 简单容斥)

    给定一个由小写字母组成的字符串,输出有多少重复的回文子序列

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    #define N 2002
    
    const int mod=1e9+7;
    
    int n;
    char s[N];
    
    int f[N][N],g[N][N];
    
    int pre[N][26],nxt[N][26];
    
    int get_f(int l,int r)
    {
        if(l>r) return 1;
        int &ans=f[l][r];
        if(ans!=-1) return ans;
        if(s[l]==s[r]) ans=get_f(l+1,r)+get_f(l,r-1);
        else ans=get_f(l+1,r)+get_f(l,r-1)-get_f(l+1,r-1);
        ans%=mod;
        if(ans<0) ans+=mod;
        return ans;
    }
    
    int get_g(int l,int r)
    {
        if(l==r) return 2;
        if(l>r) return 1;
        int &ans=g[l][r];
        if(ans!=-1) return ans;
        if(s[l]!=s[r]) ans=get_g(l+1,r)+get_g(l,r-1)-get_g(l+1,r-1);
        else
        {
            if(nxt[l][s[l]-'a']>=r && pre[r][s[r]-'a']<=l) ans=get_g(l+1,r-1)*2+1;
            else if(nxt[l][s[l]-'a']==pre[r][s[r]-'a']) ans=get_g(l+1,r-1)*2;
            else ans=get_g(l+1,r-1)*2-get_g(nxt[l][s[l]-'a']+1,pre[r][s[r]-'a']-1);
        }
        ans%=mod;
        if(ans<0) ans+=mod;
        return ans;
    }
    
    void cal()
    {
        for(int i=1;i<=n;++i)
        {
            for(int j=i+1;j<=n;++j)
                if(!nxt[i][s[j]-'a']) nxt[i][s[j]-'a']=j;
            for(int j=i-1;j;--j)
                if(!pre[i][s[j]-'a']) pre[i][s[j]-'a']=j;
        }
    }
    
    int main()
    {
        freopen("library.in","r",stdin);
        freopen("library.out","w",stdout);
        scanf("%s",s+1);
        n=strlen(s+1);
        memset(f,-1,sizeof(f));
        int all=get_f(1,n);
        cal();
        memset(g,-1,sizeof(g));
        int dif=get_g(1,n);
        int ans=all-dif;
        if(ans<0) ans+=mod;
        printf("%d",ans);
    }

    爆搜代码

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    int n;
    char s[2002];
    
    char tt[2002],t[2002];
    int L;
    
    int ans,sum;
    
    int cnt[27];
    
    void find(int now,int len,int ok)
    {
        if(ok==len) 
        {
            sum++;
            return;
        }
        for(int i=now+1;i<=n;++i)
            if(t[ok+1]==s[i]) find(i,len,ok+1);
    }
    
    void dfs(int len) 
    {
        for(int i=0;i<26;++i)
        {
            tt[len]=char(i+'a');
            L=0;
            for(int j=len;j;--j) t[++L]=tt[j];
            for(int j=2;j<=len;++j) t[++L]=tt[j];
            sum=0;
            find(0,L,0);
            if(sum>1) ans+=sum-1;
            if(sum) dfs(len+1);
        }
    }
    
    void dfs2(int len)
    {
        for(int i=0;i<26;++i)
        {
            tt[len]=char(i+'a');
            L=0;
            for(int j=len;j;--j) t[++L]=tt[j];
            for(int j=1;j<=len;++j) t[++L]=tt[j];
            sum=0;
            find(0,L,0);
            if(sum>1) ans+=sum-1;
            if(sum) dfs2(len+1);
        }
    }
    
    int main()
    {
        freopen("library.in","r",stdin);
        freopen("library.out","w",stdout);
        scanf("%s",s+1);
        n=strlen(s+1);
        for(int i=1;i<=n;++i) cnt[s[i]-'a']++;
        dfs(1);
        dfs2(1);
        printf("%d",ans);
    }
  • 相关阅读:
    5-JVM常用的命令
    4-JVM 参数
    3-JVM垃圾回收算法和垃圾收集器
    2-JVM内存结构
    1-JVM基础
    非常短的git学习笔记
    白话马尔科夫链蒙特卡罗方法(MCMC)
    写了个小游戏,来玩
    胡小兔的 高考2019 游记
    机房志 | 一篇中二的文章
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8719474.html
Copyright © 2011-2022 走看看