original link - https://cn.vjudge.net/contest/320257#problem/K
题意:
求包含串A,BA,BA,B的串的个数,要求满足num(′R′)=n,num(′D′)=mnum('R')=n,num('D')=mnum(′R′)=n,num(′D′)=m
解析:
先把两个串做一个AC自动机,然后dp的过程有点类似一个一个字符塞到答案串中。
dp[i][j][sta][node]dp[i][j][sta][node]dp[i][j][sta][node]表示已经塞iii个RRR,jjj个DDD,状态为stastasta(1表示满足AAA,2表示满足BBB,3表示两个都满足),AC自动机上的结点为nodenodenode,这种状态下的数量。
每次会尝试塞RRR和DDD,转移到相应结点,如果发现此结点为AAA的结尾,则sta∣1sta|1sta∣1。
最后所有的答案为:∑dp[n][m][3][i]\sum dp[n][m][3][i]∑dp[n][m][3][i]。
注意: 在buildbuildbuild的时候,要维护结点的值。如果fail[now]fail[now]fail[now]存在sta=2sta=2sta=2,那么显然nownownow也可以作为BBB串的结尾。
代码:
/*
* Author : Jk_Chen
* Date : 2019-08-21-18.55.46
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n';
const LL mod=1e9+7;
LL rd() {
LL ans=0;
char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))
last=ch,ch=getchar();
while(ch>='0' && ch<='9')
ans=ans*10+ch-'0',ch=getchar();
if(last=='-')
ans=-ans;
return ans;
}
/*_________________________________________________________head*/
const int maxn=109;
namespace AC {
const int K=2;
int nex[maxn<<1][K],fail[maxn<<1],End[maxn<<1],root,cnt;
int newnode() {
++cnt;
for(int i=0; i<K; i++)
nex[cnt][i]=-1;
End[cnt]=0;
return cnt;
// 1~ cnt
}
void init() {
cnt=0;
root=newnode();
}
void insert(char *str,int len,int id) {
int now=root;
for(int i=0; i<len; i++) {
if(nex[now][str[i]=='R']==-1)
nex[now][str[i]=='R']=newnode();
now=nex[now][str[i]=='R'];
}
End[now]=1<<id;
}
void build() { //建立ac自动机
queue<int>que;
for(int i=0; i<K; i++) {
if(nex[root][i]==-1)
nex[root][i]=root;
else {
fail[nex[root][i]]=root;
que.push(nex[root][i]);
}
}
while(!que.empty()) {
int now=que.front();
que.pop();
End[now] |= End[fail[now]]; // 满足y的串一定满足x+y
for(int i=0; i<K; i++) {
if(nex[now][i]==-1)
nex[now][i]=nex[fail[now]][i];
else {
fail[nex[now][i]]=nex[fail[now]][i];
que.push(nex[now][i]);
}
}
}
}
}
char A[maxn],B[maxn];
int dp[maxn][maxn][4][maxn<<1];
inline void Add(int &a,int b) {
a=(a+b)-(a+b>=mod)*mod;
}
int main() {
int t=rd();
while(t--) {
int n=rd(), m=rd();
gets(A), gets(B);
AC::init();
AC::insert(A,strlen(A),0);
AC::insert(B,strlen(B),1);
AC::build();
mmm(dp,0);
dp[0][0][0][1]=1;
// R 1 D 0
rep(i,0,n)rep(j,0,m)rep(sta,0,3)rep(node,1,AC::cnt) {
int n1=AC::nex[node][1], n0=AC::nex[node][0];
Add(dp[i+1][j][sta|AC::End[n1]][n1], dp[i][j][sta][node]);
Add(dp[i][j+1][sta|AC::End[n0]][n0], dp[i][j][sta][node]);
}
int ans=0;
rep(i,1,AC::cnt) {
Add(ans,dp[n][m][3][i]);
}
printf("%d\n",ans);
}
}