题意:
给你三个字符串,这些字符串有些单词模糊不可认了,用"?“来代表。 现在你可以用任意英文小写字母来代表它们。要求是使得给定的三个字符串中 所有的”?"被你认定的字母代替后,各不相同且按字典序出现。问有多少种方式。
输入:先给出一个数字N,代表数据组数。 接下来3*N行,每行给出一个字符串。长度<=1000 000
输出:输出结果 Mod 10^9+9
参考自:https://www.cnblogs.com/SGCollin/p/9751265.html
思路:
将这三个字符串一起处理,’?'特殊对待,可视为任意字符。小于最长长度的部分定义为0,不会影响相互间大小关系。
字符串间的状态,可以分为四种
定义 代表之前状态为a,当前状态为b,且当前的三个字符为i,j,k时候的转移方案数。
在定义
代表处理完前
个字符,当前状态为
的方案数。
转移的方式就是
最终要保证状态为 ,所以结果为
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const ll mod = 1e9 + 9;
ll f[maxn][4],g[4][4][28][28][28];
int len,len1,len2,len3;
int a1[maxn],a2[maxn],a3[maxn];
char s1[maxn],s2[maxn],s3[maxn];
void Pre() {
int l1,r1,l2,r2,l3,r3;
for(int i = 0;i <= 27;i++) {
for(int j = 0;j <= 27;j++) {
for(int k = 0;k <= 27;k++) {
if(i == 27) l1 = 1,r1 = 26;else l1 = r1 = i;
for(int x = l1;x <= r1;x++) {
if(j == 27) l2 = 1,r2 = 26;else l2 = r2 = j;
for(int y = l2;y <= r2;y++) {
if(k == 27) l3 = 1,r3 = 26;else l3 = r3 = k;
for(int z = l3;z <= r3;z++) {
if(x == y && y == z) g[0][0][i][j][k]++;
if(x < y && y == z) g[0][1][i][j][k]++;
if(x == y && y < z) g[0][2][i][j][k]++;
if(x < y && y < z) g[0][3][i][j][k]++;
if(y < z) g[1][3][i][j][k]++;
if(y == z) g[1][1][i][j][k]++;
if(x < y) g[2][3][i][j][k]++;
if(x == y) g[2][2][i][j][k]++;
g[3][3][i][j][k]++;
}
}
}
}
}
}
}
void init() {
scanf("%s%s%s",s1 + 1,s2 + 1,s3 + 1);
len1 = strlen(s1 + 1);len2 = strlen(s2 + 1);len3 = strlen(s3 + 1);
len = max(len1,max(len2,len3));
for(int i = 1;i <= len1;i++) a1[i] = s1[i] == '?' ? 27 : s1[i] - 'a' + 1;
for(int i = 1;i <= len2;i++) a2[i] = s2[i] == '?' ? 27 : s2[i] - 'a' + 1;
for(int i = 1;i <= len3;i++) a3[i] = s3[i] == '?' ? 27 : s3[i] - 'a' + 1;
for(int i = len1 + 1;i <= len;i++) a1[i] = 0;
for(int i = len2 + 1;i <= len;i++) a2[i] = 0;
for(int i = len3 + 1;i <= len;i++) a3[i] = 0;
}
int main() {
Pre();
int T;scanf("%d",&T);
while(T--) {
init();
for(int i = 0;i <= len;i++) {
for(int j = 0;j <= 3;j++) {
f[i][j] = 0;
}
}
f[0][0] = 1;
for(int i = 1;i <= len;i++) {
for(int k = 0;k <= 3;k++) {
if(f[i - 1][k]) {
for(int j = 0;j <= 3;j++) {
f[i][j] += f[i - 1][k] * g[k][j][a1[i]][a2[i]][a3[i]] % mod;
f[i][j] %= mod;
}
}
}
}
printf("%lld\n",f[len][3]);
}
return 0;
}