Vocabulary Gym - 100543F 神奇的dp

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring> 
#define ll long long
const int N = 1E6;
const int mod = 1E9 + 9;
using namespace std;
int dp[5][5][30][30][30]; //预处理出a,b, c字符串中任意字母 和中间两个任意符号的情况数
void init()
{
	for (int i = 0; i <= 27; ++i)
		for (int j = 0; j <= 27; ++j)
			for (int k = 0; k <= 27; ++k)
			{

				//如果是27  也就是 要填的数字
				//那么li ri 就表示左右边界
				int li = (i == 27) ? 1 : i, ri = (i == 27) ? 26 : i;
				for (int x = li; x <= ri; ++x)
				{

					int lj = (j == 27) ? 1 : j, rj = (j == 27) ? 26 : j;
					for (int y = lj; y <= rj; ++y)
					{

						int lk = (k == 27) ? 1 : k, rk = (k == 27) ? 26 : k;
						for (int z = lk; z <= rk; ++z)
						{
							dp[3][3][i][j][k]++;
							// 
							if (x == y)
								dp[1][1][i][j][k]++;
							if (y == z)
								dp[2][2][i][j][k]++;
							
							if (x < y)
								dp[1][3][i][j][k]++;
							if (y < z)
								dp[2][3][i][j][k]++;
								
							if (x == y && y == z)
								dp[0][0][i][j][k]++;
							if (x == y && y < z)
								dp[0][1][i][j][k]++;
							if (x < y && y == z)
								dp[0][2][i][j][k]++;
								
							if (x < y && y < z)
								dp[0][3][i][j][k]++;
						}
					}
				}
			}
}
char str[N + 10];
int arr[5][N + 10];
int f[5][N + 10];
int main()
{
	init(); //预处理所有转移状态 
	int T;
	cin>>T;
	while (T--)
	{
		int n1, n2, n3;
		//读入串
		cin>> str + 1;
		n1 = strlen(str + 1);
		//如果是问号 标记为27
		for (register int i = 1; i <= n1; ++i)
			arr[1][i] = (str[i] == '?' ? 27 : str[i] - 'a' + 1);
		cin>> str + 1;
		n2 = strlen(str + 1);
		for (register int i = 1; i <= n2; ++i)
			arr[2][i] = (str[i] == '?' ? 27 : str[i] - 'a' + 1);
		cin>> str + 1;
		n3 = strlen(str + 1);
		for (register int i = 1; i <= n3; ++i)
			arr[3][i] = (str[i] == '?' ? 27 : str[i] - 'a' + 1);


		//统计最长
		int maxlen = max(n1, n2);
		maxlen = max(maxlen, n3);
		//初始化
		for (int i = n1 + 1; i <= maxlen; i++)
			arr[1][i]=0;
		for (int i = n2 + 1; i <= maxlen; i++)
			arr[2][i]=0;
		for (int i = n3 + 1; i <= maxlen; i++)
			arr[3][i]=0;


		f[0][0] = 1;
		for (register int i = 1; i <= maxlen; ++i)
		{
			//初始化,考虑到第j个串的前i个字母是的方案数
			for (register int j = 0; j <= 3; ++j)
				f[j][i] = 0;
			for (register int j = 0; j <= 3; ++j)
				for (register int k = 0; k <= 3; ++k)								 
					f[j][i] = (f[j][i] + 1ll *f[k][i - 1] * dp[k][j][arr[1][i]][arr[2][i]][arr[3][i]] % mod) % mod;
		}
		cout<<f[3][maxlen]<<endl;
	}
	return 0;
}
posted @ 2020-05-11 09:40  晴屿  阅读(91)  评论(0编辑  收藏  举报