首页 > 其他分享 >Educational Codeforces Round 97 (Rated for Div 2) G. Death DBMS

Educational Codeforces Round 97 (Rated for Div 2) G. Death DBMS

时间:2023-09-23 10:55:39浏览次数:30  
标签:std Educational Rated val int tr Codeforces vector aca

Problem - G - Codeforces

题意

给定n个字符串,每个字符串有一个值val,n次询问,每次给一个字符串,询问给定n个字符串中是询问字符串子串的值的最大值

分析

多模式匹配,从中找到给定串的子串,想到建立ac自动机,对于给定字符串,在自动机上面匹配时,沿fail指针向上跳并求最大值即可,由于n个字符串总长度M=3E5,所有长度不同的字符串最多有$\sqrt{M}$,所以fai树中的链长最多不超过$\sqrt{M}$,由于匹配字符串长度不超过M=3E5,所以总跳数小于M$\sqrt{M}$,对于每个结点的可能存在多个给定串,使用muityset维护val,总复杂度O(nlogn + M$\sqrt{M}$)

#include <bits/stdc++.h>

using i64 = long long;

struct ACA
{
    std::vector<std::array<int, 26>> tr;
    std::vector<int> ne;
    std::vector<std::set<int>> id;
    std::vector<int> invid;
    std::vector<std::multiset<int>> val;
    std::vector<int> cnt;
    std::vector<int> q;
    std::vector<std::vector<int>> adj;
    int idx;

    ACA(int n) : tr(n + 1), ne(n + 1), invid(n + 1), id(n + 1), cnt(n + 1), q(n + 1), val(n + 1)
    {
        adj.assign(n + 1, std::vector<int>());
        idx = 0;
    }

    void insert(std::string s, int x)
    {
        int p = 0;
        int sz = s.size();
        for (int i = 0; i < sz; i++)
        {
            int t = s[i] - 'a';
            if (!tr[p][t])
                tr[p][t] = ++idx;
            p = tr[p][t];
        }
        id[p].insert(x); // p是x结尾的数据
        val[p].insert(0);
        invid[x] = p;
    }

    void build()
    {
        int hh = 0, tt = -1;
        for (int i = 0; i < 26; i++)
            if (tr[0][i])
                q[++tt] = tr[0][i];
        while (hh <= tt)
        {
            int p = q[hh++];
            adj[ne[p]].push_back(p);
            for (int i = 0; i < 26; i++)
                if (!tr[p][i])
                    tr[p][i] = tr[ne[p]][i];
                else
                {
                    ne[tr[p][i]] = tr[ne[p]][i];
                    q[++tt] = tr[p][i];
                }
        }
    }

    void query(std::string str)
    {
        int sz = str.size();
        for (int i = 0, now = 0; i < sz; i++)
        {
            int t = str[i] - 'a';
            now = tr[now][t];
            int p = now;
            cnt[p]++; // 对应的节点加一,在最后bfs是保证前节点全部加一
        }
    }

    void dfs(int u)
    {
        for (auto v : adj[u])
        {
            dfs(v);
            cnt[u] += cnt[v];
        }
    }
};

constexpr int N = 3E5;

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    ACA aca(N);

    int n, q;
    std::cin >> n >> q;
    std::vector<int> a(n + 1, 0);
    for (int i = 1; i <= n; i++)
    {
        std::string s;
        std::cin >> s;
        aca.insert(s, i);
    }

    aca.build();

    std::vector<int> up(aca.idx + 1);

    auto dfs1 = [&](auto self, int u, int last) -> void
    {
        up[u] = last;
        if (aca.id[u].size())
            last = u;
        for (auto v : aca.adj[u])
            self(self, v, last);
    };

    dfs1(dfs1, 0, 0);

    while (q--)
    {
        int op;
        std::cin >> op;
        if (op == 1)
        {
            int x, y;
            std::cin >> x >> y;
            int id = aca.invid[x];
            aca.val[id].erase(aca.val[id].find(a[x]));
            aca.val[id].insert(y);
            a[x] = y;
        }
        else
        {
            std::string str;
            std::cin >> str;
            int ans = -1;
            for (int i = 0, now = 0; i < str.size(); i++)
            {
                int t = str[i] - 'a';
                now = aca.tr[now][t];
                int p = now;
                while (p)
                {
                    if (aca.val[p].size())
                        ans = std::max(ans, *(--aca.val[p].end()));
                    p = up[p];
                }
            }
            std::cout << ans << "\n";
        }
    }
    return 0;
}

标签:std,Educational,Rated,val,int,tr,Codeforces,vector,aca
From: https://www.cnblogs.com/muxinchegnfeng/p/17723994.html

相关文章

  • Codeforces Round 898 (Div. 4)(A-H)
    CodeforcesRound898(Div.4)A.给abc的某个排列,问能否最多交换一次让排列变成abc直接看有几个不在原位就行查看代码#include<iostream>usingnamespacestd;voidsolve(){ chara,b,c; cin>>a>>b>>c; intans=0; if(a!='a')ans++; if(b!='b')ans++; ......
  • Tinkoff Internship Warmup Round 2018 and Codeforces Round 475 (Div. 1) D. Freque
    Problem-D-Codeforces题意给定一个字符串,n次询问,每次询问一个字符串在给定字符串的子串中出现k次时子串的最小长度分析多模式匹配,想到使用AC自动机,由于询问子串总长度不超过M=1E5,那么对于长度不同的串最多有$\sqrt{M}$,那么我们队fail树中最长的链长度小于$\sqrt{M}$,对原......
  • # [Codeforces Round 898 (Div. 4)] E. Building an Aquarium
    CodeforcesRound898(Div.4)E.BuildinganAquariumYoulovefish,that'swhyyouhavedecidedtobuildanaquarium.Youhaveapieceofcoralmadeof\(n\)columns,the\(i\)-thofwhichis\(ai\)unitstall.Afterwards,youwillbuildat......
  • Codeforces Round 898 (Div. 4)
    CodeforcesRound898(Div.4)A.ShortSort解题思路:遍历所有交换情况,看是否有\(abc\).代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;constintN=1e6+10;constintM=2*M;typedefpair<int,int>pii;#definefifirst#define......
  • CodeTON Round 6 (Div. 1 + Div. 2, Rated, Prizes!)
    Preface这场因为晚上去做大物实验了,到寝室洗完澡都11点了,就没现场打了的说后面补题发现前5题都很一眼,虽然补题的时候E题FST了(T在了42个点,如果放在比赛就FST了),F题还是很有意思的一个题目的说A.MEXanizedArray简单讨论一下即可#include<cstdio>#include<iostream>#include......
  • Educational Codeforces Round 123 - D(思维题)
    目录D.CrossColoringD.CrossColoring题意$n\timesm$的方格纸上进行q次操作,每次操作选择某整行x和某整列y,使得行x和列y均涂上k种颜色中的一种。问你最终的方案数思路倒序考虑操作,因为对于同一行或者同一列,后面的操作覆盖前面的操作利用数组标记某行或者某......
  • CodeTON Round 6 (Div. 1 + Div. 2, Rated, Prizes!) 更新ing
    A.MEXanizedArray题意给你三个数\(n\)、\(k\)、\(x\),让你求出能否构造出mex为\(k\),且所有数字都不超过\(x\),大小为\(n\)的数组。线索1如果有存在-1情况,先想啥时候不可能,如果能一下子找到-1的情况,这个题会很简单,因为可以的情况反推过去很容易,如果特判复杂就想想是不是诈骗规......
  • Educational Codeforces Round 154 (Rated for Div. 2) A-D
    传送门:edu154/div2A.PrimeDeletion题意:给定一个0-9的排列,要求一个长度>=2的子序列,使得该子序列是质数做法:考虑31或者13即可。不过当时没有立刻想到,感觉1000以内的质数必有答案,打了暴力。用时就多了点。Code#include<bits/stdc++.h>usingnamespacestd;intpri[10......
  • Educational Codeforces Round 143
    A.TwoTowers#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definempmake_pairusingpii=pair<int,int>;usingvi=vector<int>;constexprintinf=1e18;voidsolve(){intn,m,cnt=0;stringa,......
  • CodeTON Round 6 (Div. 1 + Div. 2, Rated, Prizes!)(A-D)
    CodeTONRound6(Div.1+Div.2,Rated,Prizes!)A.让你找mex为k的n个数,这n个数从0-x,问n个数的和最大值是多少先判断不行的。然后行的肯定有0-k-1,剩下还有就选x就行。查看代码#include<iostream>usingnamespacestd;typedeflonglongll;voidsolve(){ intn,k,x;......