题解 穿越广场

传送门

考场上觉得是个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;
}
posted @ 2021-09-21 21:43  Administrator-09  阅读(2)  评论(0编辑  收藏  举报