题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=4043

题解

首先补全字符串。

f[i][j]f[i][j]表示字符串的前ii位,jj00代表三个串字典序都相等,11代表前两个串字典序相等而第二个<第三个,22代表第一个<第二个=第三个,33代表第一个<第二个<第三个,这样如果直接转移显然非常麻烦。

考虑设g[i][j][k][s][t]g[i][j][k][s][t]表示三个串现在的字符分别为i,j,ki,j,k,状态从ss转移到tt的方案数,这样枚举i,j,ki,j,k代表的字符顺序,转移非常显然,用这个来转移f[i][j]f[i][j]也很显然了。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

const int maxn=1000000;
const int mod=1000000009;

int n,g[30][30][30][4][4],f[maxn+10][4],ch[3][maxn+10];
char s[3][maxn+10];

int main()
{
  for(int i=0; i<=27; ++i)
    {
      for(int j=0; j<=27; ++j)
        {
          for(int k=0; k<=27; ++k)
            {
              int li,ri,lj,rj,lk,rk;
              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 a=li; a<=ri; ++a)
                {
                  for(int b=lj; b<=rj; ++b)
                    {
                      for(int c=lk; c<=rk; ++c)
                        {
                          if((a<b)&&(b<c))
                            {
                              ++g[i][j][k][0][3];
                            }
                          else if((a<b)&&(b==c))
                            {
                              ++g[i][j][k][0][2];
                            }
                          else if((a==b)&&(b<c))
                            {
                              ++g[i][j][k][0][1];
                            }
                          else if((a==b)&&(b==c))
                            {
                              ++g[i][j][k][0][0];
                            }
                          if(a==b)
                            {
                              ++g[i][j][k][1][1];
                            }
                          else if(a<b)
                            {
                              ++g[i][j][k][1][3];
                            }
                          if(b==c)
                            {
                              ++g[i][j][k][2][2];
                            }
                          else if(b<c)
                            {
                              ++g[i][j][k][2][3];
                            }
                          ++g[i][j][k][3][3];
                        }
                    }
                }
            }
        }
    }
  int t=read();
  while(t--)
    {
      scanf("%s%s%s",s[0]+1,s[1]+1,s[2]+1);
      n=0;
      for(int i=0; i<3; ++i)
        {
          n=std::max(n,(int)strlen(s[i]+1));
        }
      for(int i=0; i<3; ++i)
        {
          int ni=strlen(s[i]+1);
          for(int j=1; j<=ni; ++j)
            {
              if(s[i][j]=='?')
                {
                  ch[i][j]=27;
                }
              else
                {
                  ch[i][j]=s[i][j]-'a'+1;
                }
            }
          for(int j=ni+1; j<=n; ++j)
            {
              ch[i][j]=0;
            }
        }
      f[0][0]=1;
      for(int i=1; i<=n; ++i)
        {
          for(int j=0; j<4; ++j)
            {
              for(int k=0; k<4; ++k)
                {
                  f[i][j]=(f[i][j]+1ll*f[i-1][k]*g[ch[0][i]][ch[1][i]][ch[2][i]][k][j])%mod;
                }
            }
        }
      printf("%d\n",f[n][3]);
      for(int i=1; i<=n; ++i)
        {
          for(int j=0; j<4; ++j)
            {
              f[i][j]=0;
            }
        }
    }
  return 0;
}