题解 穿越广场
考场上觉得是个AC自动机+DP,但当一个字符串是另一个的后缀时不会处理,于是就没写
但其实直接写个不管后缀的情况可以有70pts……
- AC自动机上判断是否包含一些字符串,对于有些字符串是其他字符串后缀情况的处理:
可以在每个节点维护一个vector或状压记录这个点包含哪些字符串,具体地,这个可以在处理fail指针的时候一并处理出来
剩下的部分很套路,令 \(dp[k][i][j][s]\) 表示在节点 \(k\),已有 \(i\) 个字符,其中 \(j\) 个是 \(R\),当前已包含的字符串状态为 \(s\)
转移较显然
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 510
#define ll long long
//#define int long long
int n, m;
int tr[N][2], tot, fail[N], f[N];
ll dp[205][205][105][4];
char s[N], t[N];
const ll mod=1e9+7;
bool vis[N][105][105];
struct sit{int fir, sec, thr; sit(){} sit(int a, int b, int c):fir(a),sec(b),thr(c){}};
inline void clear(int a) {tr[a][0]=tr[a][1]=0; fail[a]=0; f[a]=0;}
inline void md(ll& a, ll b) {a+=b; a=a>=mod?a-mod:a;}
void ins(char* c, int bel) {
int *t;
for (int p=0; ; p=*t) {
t=&tr[p][*c=='R'?0:1];
if (!*t) {*t=++tot; clear(tot);}
if (!*(++c)) {f[*t]=bel; return ;}
}
}
void build() {
queue<int> q;
int u=0;
fail[u]=u;
for (int i=0; i<2; ++i)
if (tr[u][i]) fail[tr[u][i]]=u, q.push(tr[u][i]);
else tr[u][i]=u;
while (q.size()) {
u=q.front(); q.pop();
for (int i=0; i<2; ++i)
if (tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i], f[tr[u][i]]|=f[tr[fail[u]][i]], q.push(tr[u][i]); //, cout<<"f: "<<f[tr[u][i]]<<endl;
else tr[u][i]=tr[fail[u]][i];
}
}
void bfs() {
queue<sit> q;
sit u(0, 0, 0);
dp[0][0][0][0]=1;
q.push(u);
while (q.size()) {
u=q.front(); q.pop();
if (u.sec==n+m) continue;
for (int j=0; j<4; ++j) {
md(dp[tr[u.fir][0]][u.sec+1][u.thr+1][j|f[tr[u.fir][0]]], dp[u.fir][u.sec][u.thr][j]);
// cout<<"tran: "<<dp[tr[u.fir][0]][u.sec+1][u.thr+1][j|f[u.fir]]<<endl;
// printf("dp[%d][%d][%d][%d] = %lld, from dp[%d][%d][%d][%d](%lld)\n", tr[u.fir][0], u.sec+1, u.thr+1, j|f[tr[u.fir][0]], dp[tr[u.fir][0]][u.sec+1][u.thr+1][j|f[tr[u.fir][0]]], u.fir, u.sec, u.thr, j, dp[u.fir][u.sec][u.thr][j]);
md(dp[tr[u.fir][1]][u.sec+1][u.thr][j|f[tr[u.fir][1]]], dp[u.fir][u.sec][u.thr][j]);
// printf("dp[%d][%d][%d][%d] = %lld, from dp[%d][%d][%d][%d](%lld)\n", tr[u.fir][1], u.sec+1, u.thr, j|f[tr[u.fir][1]], dp[tr[u.fir][1]][u.sec+1][u.thr][j|f[tr[u.fir][1]]], u.fir, u.sec, u.thr, j, dp[u.fir][u.sec][u.thr][j]);
}
if (!vis[tr[u.fir][0]][u.sec+1][u.thr+1]) q.push(sit(tr[u.fir][0], u.sec+1, u.thr+1)), vis[tr[u.fir][0]][u.sec+1][u.thr+1]=1;
if (!vis[tr[u.fir][1]][u.sec+1][u.thr]) q.push(sit(tr[u.fir][1], u.sec+1, u.thr)), vis[tr[u.fir][1]][u.sec+1][u.thr]=1;
}
}
signed main()
{
freopen("square.in", "r", stdin);
freopen("square.out", "w", stdout);
int T;
scanf("%d", &T);
while (T--) {
tot=0;
clear(0);
memset(dp, 0, sizeof(dp));
memset(vis, 0, sizeof(vis));
memset(f, 0, sizeof(f));
scanf("%d%d%s%s", &m, &n, s, t);
// cout<<n<<' '<<m<<endl;
ins(s, 1); ins(t, 2);
// cout<<"tot: "<<tot<<endl;
build(); bfs();
ll ans=0;
for (int i=0; i<=tot; ++i) md(ans, dp[i][n+m][m][3]);
printf("%lld\n", ans);
}
return 0;
}