HDU - 4758 Walk Through Squares (AC自动机+DP)

Description

On the beaming day of 60th anniversary of NJUST, as a military college which was Second Artillery Academy of Harbin Military Engineering Institute before, queue phalanx is a special landscape.

Here is a M*N rectangle, and this one can be divided into M*N squares which are of the same size. As shown in the figure below:

01--02--03--04

|| || || ||

05--06--07--08

|| || || ||

09--10--11--12

Consequently, we have (M+1)*(N+1) nodes, which are all connected to their adjacent nodes. And actual queue phalanx will go along the edges.

The ID of the first node,the one in top-left corner,is 1. And the ID increases line by line first ,and then by column in turn ,as shown in the figure above.

For every node,there are two viable paths:

(1)go downward, indicated by ‘D‘;

(2)go right, indicated by ‘R‘;

The current mission is that, each queue phalanx has to walk from the left-top node No.1 to the right-bottom node whose id is (M+1)*(N+1).

In order to make a more aesthetic marching, each queue phalanx has to conduct two necessary actions. Let‘s define the action:

An action is started from a node to go for a specified travel mode.

So, two actions must show up in the way from 1 to (M+1)*(N+1).

For example, as to a 3*2 rectangle, figure below:

01--02--03--04

|| || || ||

05--06--07--08

|| || || ||

09--10--11--12

Assume that the two actions are (1)RRD (2)DDR

As a result , there is only one way : RRDDR. Briefly, you can not find another sequence containing these two strings at the same time.

If given the N, M and two actions, can you calculate the total ways of walking from node No.1 to the right-bottom node ?

Input

The first line contains a number T,(T is about 100, including 90 small test cases and 10 large ones) denoting the number of the test cases.

For each test cases,the first line contains two positive integers M and N(For large test cases,1<=M,N<=100, and for small ones 1<=M,N<=40). M denotes the row number and N denotes the column number.

The next two lines each contains a string which contains only ‘R‘ and ‘D‘. The length of string will not exceed 100. We ensure there are no empty strings and the two strings are different.

Output

For each test cases,print the answer MOD 1000000007 in one line.

Sample Input

 2
3 2
RRD
DDR
3 2
R
D 

Sample Output

 1
10 

题意:给你两串,求用m个R,n个D能组成多少个包含这两个串

思路:先构造一个AC自动机记录每个状态包含两个串的状态,然后利用dp[i][j][k][s]表示i个R,j个D,此时AC自动机状态位置到k的时候,状态为s时的个数进行转移

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int mod = 1e9+7;

int dp[110][110][220][4];
int n,m;
int nxt[420][2],fail[420],end[420];
int root,cnt;

inline int change(char ch) {
	if (ch == 'R')
		return 0;
	else return 1;
}

inline int newNode() {
	for (int i = 0; i < 2; i++)
		nxt[cnt][i] = -1;
	end[cnt++] = 0;
	return cnt-1;
}

inline void init() {
	cnt = 0;
	root = newNode();
}

inline void insert(char buf[], int id) {
	int len = strlen(buf);
	int now = root;
	for (int i = 0; i < len; i++) {
		if (nxt[now][change(buf[i])] == -1)
			nxt[now][change(buf[i])] = newNode();
		now = nxt[now][change(buf[i])];
	}
	end[now] |= (1<<id);
}

inline void build() {
	queue<int> q;
	fail[root] = root;
	for (int i = 0; i < 2; i++)
		if (nxt[root][i] == -1)
			nxt[root][i] = root;
		else {
			fail[nxt[root][i]] = root;
			q.push(nxt[root][i]);
		}

	while (!q.empty()) {
		int now = q.front();
		q.pop();
		end[now] |= end[fail[now]];
		for (int i = 0; i < 2; i++)
			if (nxt[now][i] == -1)
				nxt[now][i] = nxt[fail[now]][i];
			else {
				fail[nxt[now][i]] = nxt[fail[now]][i];
				q.push(nxt[now][i]);
			}
	}
}

inline int solve() {
	dp[0][0][0][0] = 1;
	for (int x = 0; x <= n; x++)
		for (int y = 0; y <= m; y++)
			for (int i = 0; i < cnt; i++)
				for (int k = 0; k < 4; k++) {
					if (dp[x][y][i][k] == 0)
						continue;
					if (x < n) {
						int cur = nxt[i][0];
						dp[x+1][y][cur][k|end[cur]] += dp[x][y][i][k];
						dp[x+1][y][cur][k|end[cur]] %= mod;;
					}
					if (y < m) {
						int cur = nxt[i][1];
						dp[x][y+1][cur][k|end[cur]] += dp[x][y][i][k];
						dp[x][y+1][cur][k|end[cur]] %= mod;
					}
				}
	int ans = 0;
	for (int i = 0; i < cnt; i++) {
		ans += dp[n][m][i][3];
		ans %= mod;
	}
	return ans;
}

char str[210];

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &m);
		init();
		for (int i = 0; i < 2; i++) {
			scanf("%s", str);
			insert(str, i);
		}

		build();
		for (int i = 0; i <= n; i++)
			for (int j = 0; j <= m; j++)
				for (int x = 0; x < cnt; x++)
					for (int y = 0; y < 4; y++)
						dp[i][j][x][y] = 0;

		printf("%d\n", solve());
	}
	return 0;
}
时间: 2024-11-05 17:34:34

HDU - 4758 Walk Through Squares (AC自动机+DP)的相关文章

hdu 4758 Walk Through Squares(AC自动机+状态压缩DP)

题目链接:hdu 4758 Walk Through Squares 题意: 给你一个n*m的网格,现在你要从(1,1)走到(n,m),每次只能向右走或者向下走,走完后会形成一个包含R,D的序列,这个序列必须要包含题目给出的两个字符串,问有多少种方案. 题解: 由于要从(1,1)走到(n,m),所以这个形成的字符串包含R和D的数量是一定的. 现在考虑dp[u][i][j][k],表示包含两种串的组合状态,走了i个D,走了j个R,走到了k这个AC自动机的节点的方案数,然后dp一下就行了.复杂度为O

HDU - 4758 Walk Through Squares (AC自己主动机+DP)

Description On the beaming day of 60th anniversary of NJUST, as a military college which was Second Artillery Academy of Harbin Military Engineering Institute before, queue phalanx is a special landscape. Here is a M*N rectangle, and this one can be

HDU 3341 Lost&#39;s revenge AC自动机+dp

Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 3757    Accepted Submission(s): 1020 Problem Description Lost and AekdyCoin are friends. They always play "number game"(A bor

Hdu 3341 Lost&#39;s revenge (ac自动机+dp+hash)

题目大意: 给出很多个DNA串,每一个串的价值为1,最后给出一个长串,要你重新排列最后的串使之它所有的子串的权值和最大. 思路分析: 最先容易想到的思路就是搜!管她3721..直接一个字符一个字符的码,然后在AC自动机上判断最后的权值.TLE哟. 然后发现搜过不去,那就dp咯.再容易想到的就是dp[i][a][b][c][d] 表示此时遍历AC自动机的节点在i,然后构成了a个A,b个G,c个C,d个T的权值. 再一看内存,500*40*40*40*40...然后...就没有然后了 再想,因为它说

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理)

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理) 题意:给出若干个模式串,总长度不超过40,对于某一个字符串,它有一个价值,对于这个价值的计算方法是这样的,设初始价值为V=1,假如这个串能匹配第k个模式串,则V=V*prime[k]*(i+len[k]),其中prime[k]表示第k个素数,i表示匹配的结束位置,len[k]表示第k个模式串的长度(注意,一个字符串可以多次匹配同意个模式串).问字符集为'A'-'Z'的字符,组成的所有的长为L的字符串,

HDU 2457 DNA repair (AC自动机 + DP)

题目链接:DNA repair 解析:给出n个致病DNA序列,给一段DNA片段,问最少修改多少个碱基才能修复这段DNA序列中的所有致病序列. AC自动机 + DP. 将n个致病DNA序列构成一个自动机. 令DP[i][j]表示长度为i走到节点j是所需改变的最少个数. 状态转移时,枚举下一步所有可能的碱基,然后判断该碱基是否达到匹配状态,若能,则安全转移,继续枚举下一个碱基:否则在不匹配的前提下,看该碱基加入之后是否跟上一状态相同,若不同,则需修复,即计数加一.若相同,直接转移即可.然后选择其中最

HDU 4057 Rescue the Rabbit (AC自动机+DP)

http://acm.hdu.edu.cn/showproblem.php?pid=4057 Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1482    Accepted Submission(s): 430 Problem Description Dr. X is a biologist,

HDU - 6086 Rikka with String AC自动机 + dp

HDU - 6086 前缀和后缀分别建AC自动机, 考虑从两端往中间dp dp[ o ][ i ][ j ][ mask ] 表示放了前面和后面o个, 第一个自动机在 i 位置, 第二个自动机在 j 位置, 拥有的目标串的状态是mask的方案数. 对于跨过两端的东西, 我们最后处理就好了. #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #def

HDU 4758 Walk Through Squares(自动机+DP)

On the beaming day of 60th anniversary of NJUST, as a military college which was Second Artillery Academy of Harbin Military Engineering Institute before, queue phalanx is a special landscape. Here is a M*N rectangle, and this one can be divided into