ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

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

Input

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

Output

输出结果 Mod 10^9+9

在末尾补0直到三个串等长,dp一下,状态表示为当前考虑了前i个位置,三个串的大小关系(1=2=3,1<2=3,1=2<3,1<2<3),预处理一下每种情况的状态转移矩阵(但矩阵乘法复杂度不优,因此直接计算)

#include<cstdio>
#include<cstring>
typedef long long i64;
const int P=1e9+9;
int T,l[3],ml,t[29][29][29][4][4],ls[29],rs[29];
int f[4],g[4];
char s[3][1000007];
void maxs(int&a,int b){if(a<b)a=b;}
int sgn(int a,int b){return 1+(a>b)-(a<b);}
#define F(i,n) for(int i=0;i<n;++i)
int main(){
    for(int i=0;i<27;++i)ls[i]=rs[i]=i;
    ls[27]=1;rs[27]=26;
    F(i,28)F(j,28)F(k,28){
        int(*A)[4]=t[i][j][k];
        for(int a=ls[i];a<=rs[i];++a)
        for(int b=ls[j];b<=rs[j];++b)
        for(int c=ls[k];c<=rs[k];++c){
            int xx=sgn(a,b),yy=sgn(b,c);
            F(x,2)F(y,2){
                int x1=(x?xx:0),y1=(y?yy:0);
                if(x1<2&&y1<2)++A[x1*2+y1][x*2+y];
            }
        }
    }
    for(scanf("%d",&T);T;--T){
        ml=0;
        F(i,3){
            scanf("%s",s[i]);
            l[i]=strlen(s[i]);
            maxs(ml,l[i]);
        }
        F(i,3){
            F(j,l[i])s[i][j]=s[i][j]=='?'?27:s[i][j]-'a'+1;
            for(int j=l[i];j<ml;++j)s[i][j]=0;
        }
        F(a,4)f[a]=g[a]=0;
        f[3]=1;
        F(i,ml){
            F(a,4)g[a]=0;
            int(*A)[4]=t[s[0][i]][s[1][i]][s[2][i]];
            F(a,4)F(b,4){
                g[a]=(g[a]+i64(f[b])*A[a][b])%P;
            }
            F(a,4)f[a]=g[a];
        }
        printf("%d\n",(f[0]+P)%P);
    }
    return 0;
}

 

posted on 2017-06-14 16:05  nul  阅读(228)  评论(0编辑  收藏  举报