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 ?
2 3 2 RRD DDR 3 2 R D
1 10
万万没想到居然出了三个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; }