链接
https://codeforces.com/contest/1149/problem/B
题解
当时没想出来,但其实顺着当时的某个思路想下去也许能够得到正解
首先考虑给定三个字符串,我怎么判定
Y
E
S
YES
YES还是
N
O
NO
NO?
显然贪心不好做
因为
d
p
dp
dp是可以优化的嘛,我可以一上来设计状态
f
l
,
i
,
j
,
k
f_{l,i,j,k}
fl,i,j,k表示考虑了串的前
l
l
l个字符,能否拼凑出三个串的长度为
i
,
j
,
k
i,j,k
i,j,k的前缀,转移的话,就枚举最后一字符放哪个串里的。看到这是一个
b
o
o
l
bool
bool类型的状态,根据经验我可以降维,那我就把最大的维
l
l
l放到值的位置上去,
f
i
j
k
f_{ijk}
fijk表示的是长度为别为
i
j
k
ijk
ijk的前缀至少用到原字符串的哪个地方
好,那么这题到这里就已经结束了
容易发现,当我对某个串
a
p
p
e
n
d
append
append一个字符的时候,我可以只做一个二维
d
p
dp
dp
减少一个字符的时候,甚至不需要
d
p
dp
dp
时间复杂度
O
(
25
0
2
Q
)
O(250^2Q)
O(2502Q)
代码
#include <bits/stdc++.h>
#define eps 1e-8
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define cl(x) memset(x,0,sizeof(x))
#define mod 1000000007ll
#define maxn 100010
using namespace std;
typedef long long ll;
int read(int x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
int f[256][256][256], table[maxn][30], N, pos[30], l1, l2, l3, Q, str[5][300];
char s[maxn];
int main()
{
int i, j, k, num;
char c;
N=read(), Q=read();
scanf("%s",s+1);
for(i=1;i<=N;i++)s[i]=s[i]-'a'+1;
for(i=1;i<=26;i++)pos[i]=N+1;
for(i=1;i<=26;i++)table[N+1][i]=N+1;
for(i=N;~i;i--)
{
for(j=1;j<=26;j++)table[i][j]=pos[j];
pos[s[i]]=i;
}
while(Q--)
{
scanf("%s",s);
// printf("opt = %c\n",s[0]);
if(s[0]=='+')
{
scanf("%d%s",&num,s);
// printf("%lld %s\n",num,s);
// fflush(stdout);
c=s[0]-'a'+1;
if(num==1)
{
l1++;
str[1][l1]=c;
for(i=0;i<=l2;i++)for(j=0;j<=l3;j++)
{
f[l1][i][j]=table[f[l1-1][i][j]][c];
if(i)f[l1][i][j]=min( f[l1][i][j], table[f[l1][i-1][j]][str[2][i]]);
if(j)f[l1][i][j]=min( f[l1][i][j], table[f[l1][i][j-1]][str[3][j]]);
}
}
else if(num==2)
{
l2++;
str[2][l2]=c;
for(i=0;i<=l1;i++)for(j=0;j<=l3;j++)
{
f[i][l2][j]=table[f[i][l2-1][j]][c];
if(i)f[i][l2][j]=min( f[i][l2][j], table[f[i-1][l2][j]][str[1][i]]);
if(j)f[i][l2][j]=min( f[i][l2][j], table[f[i][l2][j-1]][str[3][j]]);
// printf("f[%lld][%lld][%lld]=%lld\n",i,l2,j,f[i][l2][j]);
}
}
else
{
l3++;
str[3][l3]=c;
for(i=0;i<=l1;i++)for(j=0;j<=l2;j++)
{
f[i][j][l3]=table[f[i][j][l3-1]][c];
if(i)f[i][j][l3]=min( f[i][j][l3], table[f[i-1][j][l3]][str[1][i]]);
if(j)f[i][j][l3]=min( f[i][j][l3], table[f[i][j-1][l3]][str[2][j]]);
}
}
}
else
{
scanf("%d",&num);
if(num==1)l1--;
if(num==2)l2--;
if(num==3)l3--;
}
if(f[l1][l2][l3]<=N)printf("YES\n");
else printf("NO\n");
}
return 0;
}