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 ?
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.
万万没想到居然出了三个AC自动机+dp的题== 这个题也是隐藏的挺深,开始想要也许是把位置单纯的做压缩?发现题意是要求从左上角走到(n+1,m+1)提供的两种方法必须都用,问有几种方法。深刻的反思自己,首先这题只能下、右所以插入字典树的时候每个节点只有两种节点,所有的26都改成2;其次,由于之前的题是单纯的字符串,dp数组开到三维,而这题是矩阵,需要开四维的数组。具体细节模仿前两个题实现了一下。然后就和
这题一样了==
#include <iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define mod 1e9+7
int num[1<<11];
int n,m,k;
struct Trie
{
int next[410][2],fail[410],end[410],dp[110][110][220][4];
int root,L;
int newnode()
{
for(int i=0;i<2;i++)next[L][i]=-1;
end[L++]=0;
return L-1;
}
void init()
{
L=0;
root=newnode();
}
void insert(char buf[],int id)
{
int len=strlen(buf);
int now=root;
for(int i=0;i<len;i++)
{
int t=buf[i]=='D'?1:0;
if(next[now][t]==-1)
next[now][t]=newnode();
now=next[now][t];
}
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]);
}
}
}
int solve()
{
memset(dp,0,sizeof(dp));
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<L;i++)
{
for(int k=0;k<(1<<2);k++)
{
if(dp[x][y][i][k]==0)continue;
int newx,newy,newi,newk;
if(x<n)
{
newx=x+1;
newy=y;
newi=next[i][0];
newk=k|end[newi];
dp[newx][newy][newi][newk]+=dp[x][y][i][k];
if(dp[newx][newy][newi][newk]>=mod)
dp[newx][newy][newi][newk]-=mod;
}
if(y<m)
{
newx=x;
newy=y+1;
newi=next[i][1];
newk=k|end[newi];
dp[newx][newy][newi][newk]+=dp[x][y][i][k];
if(dp[newx][newy][newi][newk]>=mod)
dp[newx][newy][newi][newk]-=mod;
}
}
}
}
int ans=0;
// for(int i=0;i<(1<<m);i++)
// {
// if(num[i]<k) continue;
for(int j=0;j<L;j++)
{
ans+=dp[n][m][j][3];
if(ans>mod)ans-=mod;
}
// }
return ans;
}
}ac;
char buf[200];
int main()
{
// freopen("cin.txt","r",stdin);
// num[0]=0;
// for(int i=0;i<(1<<3);i++)
// {
// num[i]=0;
// for(int j=0;j<10;j++)
// if(i&(1<<j)) num[i]++;
// }
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ac.init();
for(int i=0;i<2;i++)
{
scanf("%s",buf);
ac.insert(buf,i);
}
ac.build();
printf("%d\n",ac.solve());
}
return 0;
}