zoukankan      html  css  js  c++  java
  • CodeForces

    题目传送门

    题解:

    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
  • 相关阅读:
    js动态创建table表格的四种方法和性能测试(转载)
    render用法汇总(转载)
    echarts 解决 X轴与Y轴数据不对应问题;X轴日期显示顺序错误问题
    数组对象按时间字符串排序(转载)
    SQL Server 取日期时间部分(转载)
    iview Table行编辑、单元格编辑(转载)
    使用C#创建Windows服务
    马士兵-synchronized
    小程序登录笔记
    Prometheus+Grafana 的方法监控 Springboot 应用
  • 原文地址:https://www.cnblogs.com/MingSD/p/10796983.html
Copyright © 2011-2022 走看看