Codefroces B. Three Religions

https://codeforces.com/contest/1150/problem/D

题意:就是先给一个单词,然后给你三个空串,然后给你一些操作,分别是在单词中取出字母加上一些字母,或者减去一些字母,问三个串有没有冲突的。用过了的字母,在没有别的串减去时是不可以用的。而且一个串的字母的取法是按照他给的操作的顺序的,比如第一次加了a第二次加了c在单词中a的前面的c不能取,只能取a后面的;

做法:不会做。。。。序列自动机+dp,看了官方题解后

dp[i][j][k]表示在他给定的操作下,分别当三个串的长度为,i,j,k的时候,三个串不重复的最小长度,

分别用几个数组进行辅助,d[x][l[x]]表示第x个串长度为l[x]时他给定的抄作的字符,ch[i][j]表示在i之后第一次出现j字母的位置

可以在O(26*N)复杂度内完成;

转移方程如下:
dp[i][j][k] = min(dp[i][j][k], ch[dp[i - 1][j][k]][d[1][i] - 'a']);
dp[i][j][k] = min(dp[i][j][k], ch[dp[i][j - 1][k]][d[2][j] - 'a']);
dp[i][j][k] = min(dp[i][j][k], ch[dp[i][j][k - 1]][d[3][k] - 'a']);

由于可以当前+操作可以进行简化,不用枚举+操作的串,所以时间复杂度为 O(q*250*250)。减操作只需要更新长度即可。

注意dp数组的初始化。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
int n, q,ch[100010][26];
char s[100010], d[5][255];
int l[5], dp[255][255][255];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> q;
	cin >> s;
	for (int i = 0; i < 26; i++) ch[n][i] = ch[n+1][i] = n + 1;
	for (int i = n - 1; i >= 0; i--)
	{
		int t = s[i] - 'a';
		for (int j = 0; j < 26; j++)
			ch[i][j] = ch[i + 1][j];
		ch[i][t] = i + 1;
	}
	memset(l, 0, sizeof(l));
	memset(dp,0,sizeof(dp)); 
	int x; char t;
	for (int p = 1; p <= q; p++)
	{
		cin >> t >> x;
		if (t == '-') l[x]--;
		else
		{
			l[x]++;
			cin >> t;
			d[x][l[x]] = t;
			int i = x == 1 ? l[x] : 0;
			for (; i <= l[1]; i++)
			{
				int j = x == 2 ? l[x] : 0;
				for (; j <= l[2]; j++)
				{
					int k = x == 3 ? l[x] : 0;
					for (; k <= l[3]; k++)
					{
						dp[i][j][k] = n + 1;
						if (i&&dp[i - 1][j][k]!=inf)
							dp[i][j][k] = min(dp[i][j][k], ch[dp[i - 1][j][k]][d[1][i] - 'a']);
						if (j&&dp[i - 1][j][k]!=inf)
							dp[i][j][k] = min(dp[i][j][k], ch[dp[i][j - 1][k]][d[2][j] - 'a']);
						if (k&&dp[i - 1][j][k]!=inf)
							dp[i][j][k] = min(dp[i][j][k], ch[dp[i][j][k - 1]][d[3][k] - 'a']);
					}
				}
			}
		}
		if (dp[l[1]][l[2]][l[3]] <= n)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/89715863