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 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

状态比较好想:设dp[i][j][k][l]:为在第行,第j列,自动机上走到k节点,包含串的情况。

转移下即可。用LL MLE啦。要换成int。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<bitset>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pair<int,int>pil;
const int INF = 0x3f3f3f3f;
const int MOD=1e9+7;
int dp[110][110][210][4];
int n,m;
struct AC{
    int next[220][2];
    int fail[220],ed[220];
    int root,L;
    int newnode()
    {
        for(int i=0;i<2;i++)
           next[L][i]=-1;
        ed[L++]=0;
        return L-1;
    }
    void init()
    {
        L=0;
        root=newnode();
    }
    int what(char c)
    {
        return c!='D';
    }
    void Insert(char buf[],int id)
    {
        int len=strlen(buf);
        int now=root;
        for(int i=0;i<len;i++)
        {
            int x=what(buf[i]);
            if(next[now][x]==-1)
                next[now][x]=newnode();
            now=next[now][x];
        }
        ed[now]|=(1<<id);
    }
    void Build_AC()
    {
        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();ed[now]|=ed[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]);
                }
            }
        }
    }
    void solve()//0:D   1:R
    {
        CLEAR(dp,0);
        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 l=0;l<(1<<2);l++)
                    {
                        if(dp[i][j][k][l])
                        {
                            if(i<n)
                            {
                                int x=next[k][0];
                                int st=l|ed[x];
                                dp[i+1][j][x][st]+=dp[i][j][k][l];
                                dp[i+1][j][x][st]%=MOD;
                            }
                            if(j<m)
                            {
                                int x=next[k][1];
                                int st=l|ed[x];
                                dp[i][j+1][x][st]+=dp[i][j][k][l];
                                dp[i][j+1][x][st]%=MOD;
                            }
                        }
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;i<L;i++)
        {
            ans+=dp[n][m][i][3];
            ans%=MOD;
        }
        printf("%d\n",ans);
    }
};
AC A;char str[110];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        A.init();
        scanf("%d%d",&m,&n);
        REP(i,2)
        {
            scanf("%s",str);
            A.Insert(str,i);
        }
        A.Build_AC();
        A.solve();
    }
    return 0;
}
/*
2
3 2
RRD
DDR
3 2
R
D
*/
时间: 2024-11-04 12:40:26

HDU 4758 Walk Through Squares(自动机+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 - 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 2825 Wireless Password(ac自动机&amp;dp)

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4022    Accepted Submission(s): 1196 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

HDU 2457 DNA repair AC自动机 + dp

http://acm.hdu.edu.cn/showproblem.php?pid=2457 首先把病毒串保存一下,然后对于每一个trie上的节点,跑一发AC自动机,建立一个trie图. 建立的时候,对应做一些修改. 比如,现在建立成了这个样子. 如果he是一个病毒串,那么应该相对应的,把she那个he的位置,标志上,它也是病毒串,也就是不能转移到这一个状态. 这个可以在buildfail的时候对应修改. dp, 设dp[i][j],表示处理到字符串的第i个,走到了AC自动机的第j个节点,变成了

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 5001 Walk (暴力、概率dp)

Walk Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 266    Accepted Submission(s): 183 Special Judge Problem Description I used to think I could be anything, but now I know that I couldn't d

HDU 2296 Ring (AC自动机 + DP)

题目链接:Ring 解析:m个有价值的串,字符串s在字符串str中的价值 = s在str中出现的次数 × s的价值.问价值最大的长度为n的串是什么. 本题需要输出字典序最小的 在DP的时候开一个数组记录结果即可. AC代码: #include <algorithm> #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace s

hdu 2825 Wireless Password(AC自动机+状压DP)

题目链接:hdu 2825 Wireless Password 题目大意:N,M,K,M个字符串作为关键码集合,现在要求长度为N,包含K个以上的关键码的字符串有多少个. 解题思路:AC自动机+dp,滚动数组,因为关键码个数不会超过10个,所以我们用二进制数表示匹配的状态.dp[i][j][k] 表示到第i个位置,j节点,匹配k个字符串. #include <cstdio> #include <cstring> #include <queue> #include <