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; }