题解:
id[ i ][ j ] 代表的是在第j个位置之后的第i个字符的位置在哪里。
dp[ i ][ j ][ k ] 代表的是 第一个串匹配到第i个位置, 第二个串匹配到第j个位置, 第三个串匹配到第k个位置之后,最后面一个字符的位置在哪里。
如果题目只询问一次,那么应该很容易想到n^3的写法。
for(int i = 0; i <= n1; ++i){ for(int j = 0; j <= n2; ++j){ for(int k = 0; k <= n3; ++k){ if(i+j+k) dp[i][j][k] = n + 1; if(i) dp[i][j][k] = min(dp[i][j][k], id[ss[0][i]-'a'][dp[i-1][j][k]]); if(j) dp[i][j][k] = min(dp[i][j][k], id[ss[1][j]-'a'][dp[i][j-1][k]]); if(k) dp[i][j][k] = min(dp[i][j][k], id[ss[2][k]-'a'][dp[i][j][k-1]]); } }
但是,在一共有q次询问的前提下,肯定是不能每次询问都直接n^3的暴力得到的。
现在假如我们知道了 dp[3][4][6]的信息。
现在在第3个串后面加了一个字符,也就是说我们需要知道dp[3][4][7]的信息。
可以观察2遍的 n^3中的结果。
其中 for i from 0 to 3
for j from 0 to 4
for k from 0 to 6 的dp值和前面没有任何不同。
唯一区别的是 :
for i from 0 to 3
for j from 0 to 4
for k from 7 to 7 的dp值会发生变化。
所以我们只需要跑一边
for k from 7 to 7
for i from 0 to 3
for k from 0 to 4的dp值,更新这一块的dp值就好了。
如果 i + 1了 或者 j + 1了也是一样的道理。
所以每次更新所跑的值都是 len ^ 2。
最后的复杂度就是 q * len ^ 2. (len <= 250)。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e5 + 100; char s[N]; int id[26][N]; int dp[255][255][255]; char ss[3][N]; void Ac(){ int n, m; scanf("%d%d", &n, &m); scanf("%s", s+1); for(int i = 0; i < 26; ++i) id[i][n+1] = n+1; for(int j = n; j >= 0; --j){ for(int i = 0; i < 26; ++i){ id[i][j] = id[i][j+1]; } if(j < n) id[s[j+1]-'a'][j] = j+1; } int l1, l2, l3, n1, n2, n3; l1 = l2 = l3 = n1 = n2 = n3 = 0; char op[5]; int t; for(int _ = 1; _ <= m; ++_){ scanf("%s", op); if(op[0] == '+'){ scanf("%d%s", &t, op); if(t == 1) { ++n1; ss[0][n1] = op[0]; for(int i = n1; i <= n1; ++i){ for(int j = 0; j <= l2; ++j){ for(int k = 0; k <= l3; ++k){ if(i+j+k) dp[i][j][k] = n + 1; if(i) dp[i][j][k] = min(dp[i][j][k], id[ss[0][i]-'a'][dp[i-1][j][k]]); if(j) dp[i][j][k] = min(dp[i][j][k], id[ss[1][j]-'a'][dp[i][j-1][k]]); if(k) dp[i][j][k] = min(dp[i][j][k], id[ss[2][k]-'a'][dp[i][j][k-1]]); } } } } if(t == 2) { ++n2; ss[1][n2] = op[0]; for(int j = n2; j <= n2; ++j){ for(int i = 0; i <= l1; ++i){ for(int k = 0; k <= l3; ++k){ if(i+j+k) dp[i][j][k] = n + 1; if(i) dp[i][j][k] = min(dp[i][j][k], id[ss[0][i]-'a'][dp[i-1][j][k]]); if(j) dp[i][j][k] = min(dp[i][j][k], id[ss[1][j]-'a'][dp[i][j-1][k]]); if(k) dp[i][j][k] = min(dp[i][j][k], id[ss[2][k]-'a'][dp[i][j][k-1]]); } } } } if(t == 3) { ++n3; ss[2][n3] = op[0]; for(int k = n3; k <= n3; ++k){ for(int i = 0; i <= l1; ++i){ for(int j = 0; j <= l2; ++j){ if(i+j+k) dp[i][j][k] = n + 1; if(i) dp[i][j][k] = min(dp[i][j][k], id[ss[0][i]-'a'][dp[i-1][j][k]]); if(j) dp[i][j][k] = min(dp[i][j][k], id[ss[1][j]-'a'][dp[i][j-1][k]]); if(k) dp[i][j][k] = min(dp[i][j][k], id[ss[2][k]-'a'][dp[i][j][k-1]]); } } } } } else { scanf("%d", &t); if(t == 1) --n1; if(t == 2) --n2; if(t == 3) --n3; } l1 = n1; l2 = n2; l3 = n3; if(dp[l1][l2][l3] != n + 1) puts("YES"); else puts("NO"); } } int main(){ Ac(); return 0; } /* 6 8 abdabc + 1 a + 1 d + 2 b + 2 c */