B. Three Religions
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
During the archaeological research in the Middle East you found the traces of three ancient religions: First religion, Second religion and Third religion. You compiled the information on the evolution of each of these beliefs, and you now wonder if the followers of each religion could coexist in peace.
The Word of Universe is a long word containing the lowercase English characters only. At each moment of time, each of the religion beliefs could be described by a word consisting of lowercase English characters.
The three religions can coexist in peace if their descriptions form disjoint subsequences of the Word of Universe. More formally, one can paint some of the characters of the Word of Universe in three colors: 1, 2, 3, so that each character is painted in at most one color, and the description of the i-th religion can be constructed from the Word of Universe by removing all characters that aren’t painted in color i.
The religions however evolve. In the beginning, each religion description is empty. Every once in a while, either a character is appended to the end of the description of a single religion, or the last character is dropped from the description. After each change, determine if the religions could coexist in peace.
Input
The first line of the input contains two integers n,q (1≤n≤100000, 1≤q≤1000) — the length of the Word of Universe and the number of religion evolutions, respectively. The following line contains the Word of Universe — a string of length n consisting of lowercase English characters.
Each of the following line describes a single evolution and is in one of the following formats:
- i c (i∈{1,2,3}, c∈{a,b,…,z}: append the character c to the end of i-th religion description.
- i (i∈{1,2,3}) – remove the last character from the i-th religion description. You can assume that the pattern is non-empty.
You can assume that no religion will have description longer than 250 characters.
Output
Write q lines. The i-th of them should be YES if the religions could coexist in peace after the i-th evolution, or NO otherwise.
You can print each character in any case (either upper or lower).
这题很是遗憾,其实自己思路都已经对了,但是因为一些愚蠢的小错误,一直在debug,导致比赛结束也没有AC,使得昨晚的Rating暴减,再次错过了黄名的机会。以后无论什么比赛都不能掉以轻心,思路一定要清晰,一定要清晰!
首先看到这题,我们先回想一下一个简化的问题,如果只有唯一的宗教,判断是否是子串。很容易想到我们需要事先处理一个nxt[100005][26]nxt[100005][26]nxt[100005][26]数组,记录模板串中每一个位置中下一个字符的最小出现位置,倒着递推即可。然后找子串就成了一个不断在nxtnxtnxt中跳下标的事情,如果跳到结尾,说明没有这个串。
回到这个问题,判断三个字符串面临的一个关键问题在于,是应该选择那一个宗教的下一个字符进行跳跃最优,事实证明贪心是不行的。注意到了每个宗教不超过250个字符,2503=15625000250^3=156250002503=15625000,很像是在做dp的数据范围。我们用dp[i][j][k]dp[i][j][k]dp[i][j][k]记录当前状态为第一个宗教的前i个字符,第二个宗教的前j个字符,第三个宗教的前k个字符,对应的下标最小值,那么它们的更新就是应该由dp[i−1][j][k],dp[i][j−1][k],dp[i][j][k−1]dp[i-1][j][k],dp[i][j-1][k],dp[i][j][k-1]dp[i−1][j][k],dp[i][j−1][k],dp[i][j][k−1]递推而来,这是因为下标最小的状态对应的字符可能来自于第一,第二,第三个宗教。
然后就不用多说了,来一个字符,就把涉及到的状态dp一次,最终需要比较dp[a[1].size()−1][a[2].size()−1][a[3].size()−1]dp[a[1].size()-1][a[2].size()-1][a[3].size()-1]dp[a[1].size()−1][a[2].size()−1][a[3].size()−1]和n的大小即可。
上代码!
#include<cstdio>
#include<string>
using namespace std;
string a[4];
char s[200005],o[2],tmp[2];
int nxt[200005][26],n,q,i,pos,g[4],dp[252][252][252];
int main()
{
scanf("%d%d%s",&n,&q,s+1);
a[1]=a[2]=a[3]="0";
for(int i=0;i<26;i++)
nxt[n][i]=nxt[n+1][i]=n+1;
for(int i=n-1;i>=0;i--)
for(int j=0;j<26;j++)
if(s[i+1]==j+'a')
nxt[i][j]=i+1;
else
nxt[i][j]=nxt[i+1][j];
while(q--)
{
scanf("%s%d",o,&i);
if(o[0]=='+')
{
scanf("%s",tmp);
a[i]+=tmp[0];
int h=tmp[0]-'a';
if(i==1)
{
int t=a[1].size()-1;
for(int j=0;j<a[2].size();j++)
for(int k=0;k<a[3].size();k++)
{
dp[t][j][k]=nxt[dp[t-1][j][k]][h];
if(j)
dp[t][j][k]=min(dp[t][j][k],nxt[dp[t][j-1][k]][a[2][j]-'a']);
if(k)
dp[t][j][k]=min(dp[t][j][k],nxt[dp[t][j][k-1]][a[3][k]-'a']);
}
}
else if(i==2)
{
int t=a[2].size()-1;
for(int j=0;j<a[1].size();j++)
for(int k=0;k<a[3].size();k++)
{
dp[j][t][k]=nxt[dp[j][t-1][k]][h];
if(j)
dp[j][t][k]=min(dp[j][t][k],nxt[dp[j-1][t][k]][a[1][j]-'a']);
if(k)
dp[j][t][k]=min(dp[j][t][k],nxt[dp[j][t][k-1]][a[3][k]-'a']);
}
}
else
{
int t=a[3].size()-1;
for(int j=0;j<a[1].size();j++)
for(int k=0;k<a[2].size();k++)
{
dp[j][k][t]=nxt[dp[j][k][t-1]][h];
if(j)
dp[j][k][t]=min(dp[j][k][t],nxt[dp[j-1][k][t]][a[1][j]-'a']);
if(k)
dp[j][k][t]=min(dp[j][k][t],nxt[dp[j][k-1][t]][a[2][k]-'a']);
}
}
}
else
a[i].pop_back();
puts(dp[a[1].size()-1][a[2].size()-1][a[3].size()-1]<=n?"YES":"NO");
}
return 0;
}

本文探讨了一种算法,用于判断三种宗教信仰描述是否能在宇宙之言中形成不相交的子序列,确保和平共存。通过预处理和动态规划策略,解决了宗教描述随时间演变的复杂问题。
199

被折叠的 条评论
为什么被折叠?



