zoukankan      html  css  js  c++  java
  • bzoj千题计划234:bzoj3802: Vocabulary

    http://www.lydsy.com/JudgeOnline/problem.php?id=3802

    dp[i][0/1/2/3]  表示前i个字母,第1、2个字符串,第2、3个字符串的关系分别为 < < , = < , < = , = =

    枚举前i-1个字母 构成的关系

    再枚举3个字符串的字母 转移

    时间复杂度为 O(N* 26^3)

    优化转移:

    转移都是dp[i-1][0/1/2/3]-->dp[i][0/1/2/3]

    预处理出f[i][j][k][s:0~3][t:0~3] 表示前面字母构成的字符串的关系为s,3个字符串分别加上1个字母i、j、k后转移到关系t的方案数

    转移的时候不枚举3个字符串的字母,枚举新的关系0~3 

    直接用f数组转移

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    #define N 1000002
    
    const int mod=1e9+9;
    
    char s1[N],s2[N],s3[N]; 
    
    int f[28][28][28][4][4];
    int dp[N][4];
    //0:i<j<k  1:i=j<k  2:i<j=k  3:i=j=k  
    
    void pre()
    {
        int li,ri,lj,rj,lk,rk;
        int t;
        for(int i=0;i<=27;++i)
            for(int j=0;j<=27;++j)
                for(int k=0;k<=27;++k)
                {
                    if(i==27) li=1,ri=26;
                    else li=ri=i;
                    if(j==27) lj=1,rj=26;
                    else lj=rj=j;
                    if(k==27) lk=1,rk=26;
                    else lk=rk=k;
                    for(int ci=li;ci<=ri;++ci)
                        for(int cj=lj;cj<=rj;++cj)
                            for(int ck=lk;ck<=rk;++ck) 
                                for(int s=0;s<=3;++s)
                                {
                                    if(!s) t=0;
                                    else if(s==1)
                                    {
                                        if(ci==cj) t=1;
                                        else if(ci<cj) t=0;
                                        else t=-1;
                                    }
                                    else if(s==2)
                                    {
                                        if(cj==ck) t=2;
                                        else if(cj<ck) t=0;
                                        else t=-1;
                                    }
                                    else
                                    {
                                        if(ci>cj || ci>ck || cj>ck) t=-1;
                                        else if(ci<cj && cj<ck) t=0;
                                        else if(ci==cj && cj<ck) t=1;
                                        else if(ci<cj && cj==ck) t=2;
                                        else t=3;
                                    }
                                    if(t>=0) f[i][j][k][s][t]++;
                                }
                }    
    } 
    
    int main()
    {
        pre();
        int T;
        scanf("%d",&T);
        int l1,l2,l3,len;
        int x,y,z;
        while(T--)
        {
            scanf("%s",s1+1);
            scanf("%s",s2+1);
            scanf("%s",s3+1);
            l1=strlen(s1+1); 
            len=l1;
            l2=strlen(s2+1);
            if(l2>len) len=l2;
            l3=strlen(s3+1);
            if(l3>len) len=l3;
            while(l1!=len) s1[++l1]='a'-1;
            while(l2!=len) s2[++l2]='a'-1;
            while(l3!=len) s3[++l3]='a'-1;
            for(int i=1;i<=len;++i)
                for(int j=0;j<=3;++j)
                    dp[i][j]=0;
            dp[0][3]=1;
            for(int i=1;i<=len;++i)
            {
                x=s1[i]-'a'+1;
                if(x<0) x=27;
                y=s2[i]-'a'+1;
                if(y<0) y=27;
                z=s3[i]-'a'+1;
                if(z<0) z=27;
                for(int j=0;j<=3;++j)
                    if(dp[i-1][j])
                        for(int k=0;k<=3;++k)
                            dp[i][k]=(dp[i][k]+(long long)dp[i-1][j]*f[x][y][z][j][k]%mod)%mod;
            }
            printf("%d
    ",dp[len][0]);
        }
    } 

    3802: Vocabulary

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 185  Solved: 68
    [Submit][Status][Discuss]

    Description

    给你三个字符串,这些字符串有些单词模糊不可认了,用"?"来代表。
    现在你可以用任意英文小写字母来代表它们。要求是使得给定的三个字符串中
    所有的"?"被你认定的字母代替后,各不相同且按字典序出现。问有多少种方式。
     

    Input

    先给出一个数字N,代表数据组数。
    接下来3*N行,每行给出一个字符串。长度<=1000 000

    Output

    输出结果 Mod 10^9+9

    Sample Input

    3
    ?heoret?cal
    c?mputer
    ?cience
    jagiellonia
    ?niversity
    kra?ow
    ?
    b
    c

    Sample Output

    42562
    52
    1
  • 相关阅读:
    centos搭建window下写的flask程序
    【MTK】iwpriv命令说明
    vs2019专业版离线安装方法
    Python文件编译成exe
    python3升级与安装
    谷歌浏览器https和flash禁用的解决方法
    SQL注入常见函数
    nmap简介与运用
    WPF 万维网对战象棋 客户端+服务端(全套可执行代码在文章末尾)
    《软件工程实践》2020春季学期教学回顾--线上教学,化弊为利
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8445495.html
Copyright © 2011-2022 走看看