正题
题目大意
给出nnn个字符串SiS_iSi,然后有些???号可以进行随便填字母。
然后要求Si<Si+1S_i<S_{i+1}Si<Si+1的情况下求方案数。
解题思路
定义fl,r,p,cf_{l,r,p,c}fl,r,p,c表示只考虑l∼rl\sim rl∼r的字符串,只考虑ppp往后的字符,且第ppp个至少为ccc时的方案数。
我们有
fl,r,p,c=fl,r,p,c+1+∑mid=lrfl,mid,p+1,0+fmid+1,r,p,cf_{l,r,p,c}=f_{l,r,p,c+1}+\sum_{mid=l}^r f_{l,mid,p+1,0}+f_{mid+1,r,p,c}fl,r,p,c=fl,r,p,c+1+mid=l∑rfl,mid,p+1,0+fmid+1,r,p,c
然后用dfsdfsdfs进行转移即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=55,XJQ=990804011;
int n,L,a[N][N],f[N][N][N][N];
char s[N];
int solve(int l,int r,int p,int c)
{int &dp=f[l][r][p][c];if(~dp) return dp;if(l>r) return dp=1;if(p>L) return dp=(l==r);if(c>26) return dp=0;dp=solve(l,r,p,c+1);for(int i=l;i<=r;i++)if(a[i][p]==c||(a[i][p]==233&&c))dp=(dp+1ll*solve(l,i,p+1,0)*solve(i+1,r,p,c+1)%XJQ)%XJQ;else break; return dp;
}
int main()
{freopen("b.in","r",stdin);freopen("b.out","w",stdout);scanf("%d",&n);memset(f,-1,sizeof(f));for(int i=1;i<=n;i++){scanf("%s",s+1);int z=0;L=max(L,z=strlen(s+1));for(int j=1;j<=z;j++)a[i][j]=(s[j]=='?'?233:s[j]-'a'+1);}printf("%d",solve(1,n,1,0));
}