HDU4758 Walk Through Squares(AC自动机+状压DP)
2016-08-08 09:19
344 查看
题目大概说有个n×m的格子,有两种走法,每种走法都是一个包含D或R的序列,D表示向下走R表示向右走。问从左上角走到右下角的走法有多少种走法包含那两种走法。
D要走n次,R要走m次,容易想到用AC自动机上的DP解决:
用两种走法的序列构造AC自动机
dp[i][j][S][k]表示D用了i个R用了j个,且当前走到自动机的S结点,已经包含的走法的状态集合是k的方案数
转移就是走R或者走D了,我用我为人人来转移
D要走n次,R要走m次,容易想到用AC自动机上的DP解决:
用两种走法的序列构造AC自动机
dp[i][j][S][k]表示D用了i个R用了j个,且当前走到自动机的S结点,已经包含的走法的状态集合是k的方案数
转移就是走R或者走D了,我用我为人人来转移
#include <set> #include <map> #include <stack> #include <queue> #include <deque> #include <cmath> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define L(i) i<<1 #define R(i) i<<1|1 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-9 #define maxn 10010 #define MOD 1000000007 int n,m; int dp[110][110][210][4]; struct Trie { int next[1010][5],fail[1010],en[1010]; int root,L,cnt; void init() { L = 0; cnt = 1; root = newnode(); } int newnode() { for(int i = 0; i <= 1; i++) next[L][i] = -1; en[L++] = 0; return L-1; } void Insert(char a[],int len) { int now = root; for(int i = 0; i < len; i++) { int x; if(a[i] == 'R') x = 0; else x = 1; if(next[now][x] == -1) next[now][x] = newnode(); now = next[now][x]; } en[now] = cnt++; } void build() { queue<int> Q; fail[root] = root; for(int i = 0; i <= 1; 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(); en[now] |= en[fail[now]]; for(int i = 0; i <= 1; 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]); } } } } void solve() { memset(dp,0,sizeof(dp)); dp[0][0][0][0] = 1; for(int i = 0; i <= n; i++) for(int j = 0; j <= m; j++) for(int k = 0; k < L; k++) { for(int c = 0; c < 4; c++) { dp[i+1][j][next[k][0]][c|en[next[k][0]]] += dp[i][j][k][c]; dp[i+1][j][next[k][0]][c|en[next[k][0]]] %= MOD; dp[i][j+1][next[k][1]][c|en[next[k][1]]] += dp[i][j][k][c]; dp[i][j+1][next[k][1]][c|en[next[k][1]]] %= MOD; } } int ans = 0; for(int i = 0; i < L; i++) { ans += dp [m][i][3]; ans %= MOD; } printf("%d\n",ans); } } ac; int main() { int t,C = 1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); ac.init(); char s1[110],s2[110]; scanf("%s%s",s1,s2); ac.Insert(s1,strlen(s1)); ac.Insert(s2,strlen(s2)); ac.build(); ac.solve(); } return 0; }
相关文章推荐
- HDU4758 Walk Through Squares(AC自动机+状压DP)
- hdu4758 Walk Through Squares (AC自动机+DP)
- hdu4758---Walk Through Squares(AC自动机+dp)
- HDU 4758-Walk Through Squares(AC自动机+状压DP)
- HDU 4758 Walk Through Squares && AC自动机+状压DP
- HDU 4758 Walk Through Squares(AC自动机+DP)
- HDU - 4758 Walk Through Squares (AC自动机+DP)
- hdu 4758 Walk Through Squares(AC自动机+状态压缩DP)
- hdu 4758 - Walk Through Squares(AC自动机+DP)现场赛
- hdu 4758 Walk Through Squares(AC自动机+DP,4级)
- hdu 4758 Walk Through Squares(AC自动机+DP,4级)
- HDU 4758 Walk Through Squares(自动机+DP)
- hdu 4758 Walk Through Squares(自动机+DP)
- hdu4758 Walk Through Squares (AC自己主动机+DP)
- hdu4758 Walk Through Squares 自动机+DP
- HDU 2825 Wireless Password(AC自动机+状压DP)
- H - Wireless Password HDU - 2825(AC自动机+状压DP)
- hdu2825 Wireless Password [AC自动机+状压dp]
- 【HDU3341】 Lost's revenge (AC自动机+状压DP)
- hdu 3341 Lost's revenge (ac自动机+状压dp)