题意:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4758
一个矩形从左上角走到右下角,向右移动用R表示,向下移动用D表示,要求满足移动序列中含有给出的两个规定子串,问一共有多少种方案?
思路:
还是经典的AC自动机+状压DP思路,类似HDU-2825:http://blog.youkuaiyun.com/bahuia/article/details/77149003
都是一个套路。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const LL MOD = 1e9 + 7;
struct ACauto {
int next[205][2], fail[205], end[205];
int root, sz;
int newnode() {
for (int i = 0; i < 2; i++)
next[sz][i] = -1;
end[sz++] = 0;
return sz - 1;
}
void init() {
sz = 0;
root = newnode();
}
int idx(char c) {
if (c == 'R') return 0;
return 1;
}
void insert(char *buf, int id) {
int len = strlen(buf);
int now = root;
for (int i = 0; i < len; i++) {
int id = idx(buf[i]);
if (next[now][id] == -1)
next[now][id] = newnode();
now = next[now][id];
}
end[now] |= (1 << id);
}
void build() {
queue <int> Q;
fail[root] = root;
for (int i = 0; i < 2; i++) {
if (next[root][i] == -1)
next[root][i] = root;
else {
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while (!Q.empty()) {
int now = Q.front(); Q.pop();
end[now] |= end[fail[now]];
for (int i = 0; i < 2; i++) {
if (next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
} ac;
int R, D;
int dp[105][105][205][4];
const char d[] = {'R', 'D'};
void solve() {
memset(dp, 0, sizeof(dp));
dp[0][0][0][0] = 1;
for (int i = 0; i <= R; i++) {
for (int j = 0; j <= D; j++) {
for (int k = 0; k < ac.sz; k++) {
for (int S = 0; S < 4; S++) {
if (dp[i][j][k][S] <= 0) continue;
if (i < R) {
int ni = i + 1, nj = j, nk = ac.next[k][0], nS = S | ac.end[nk];
dp[ni][nj][nk][nS] = ((LL)dp[ni][nj][nk][nS] + dp[i][j][k][S]) % MOD;
}
//cout << i << " " << j << " " << k << " " << S << " (" << dp[i][j][k][S] << ") ---> " << ni << " " << nj << " " << nk << " " << nS <<" (" << dp[ni][nj][nk][nS] << ") " << endl;
if (j < D) {
int ni = i, nj = j + 1, nk = ac.next[k][1], nS = S | ac.end[nk];
dp[ni][nj][nk][nS] = ((LL)dp[ni][nj][nk][nS] + dp[i][j][k][S]) % MOD;
}
//cout << i << " " << j << " " << k << " " << S << " (" << dp[i][j][k][S] << ") ---> " << ni << " " << nj << " " << nk << " " << nS << " (" << dp[ni][nj][nk][nS] << ") " << endl;
}
}
}
}
LL ans = 0;
for (int i = 0; i < ac.sz; i++) {
ans = (ans + dp[R][D][i][3]) % MOD;
}
printf("%I64d\n", ans);
}
char str[1005];
int main() {
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &R, &D);
ac.init();
for (int i = 0; i < 2; i++) {
scanf("%s", str);
ac.insert(str, i);
}
ac.build();
/*for (int i = 0; i < ac.sz; i++) {
printf("%d : ", i);
for (int j = 0; j < 2; j++)
printf("%d ", ac.next[i][j]);
printf("\n");
}*/
solve();
}
return 0;
}