CodeForces - 1150 D Three Religions

题目传送门

题解:

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]]);
        }
    }
View Code

但是,在一共有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
*/
View Code

猜你喜欢

转载自www.cnblogs.com/MingSD/p/10796983.html