标签:efi bottom cpp travel aes roo mono push end
Description
Input
Output
Sample Input
2 3 2 RRD DDR 3 2 R D
Sample Output
1 10
思路:先构造一个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; }
HDU - 4758 Walk Through Squares (AC自己主动机+DP)
标签:efi bottom cpp travel aes roo mono push end
原文地址:http://www.cnblogs.com/yfceshi/p/7069187.html