【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组

E. e-Government

time limit per test: 1 second
memory limit per test: 256 megabytes
input: standard input
output: standard output

The best programmers of Embezzland compete to develop a part of the project called "e-Government" — the system of automated statistic collecting and press analysis.

We know that any of the k citizens can become a member of the Embezzland government. The citizens' surnames are a1, a2, ..., ak. All surnames are different. Initially all k citizens from this list are members of the government. The system should support the following options:

  • Include citizen ai to the government.
  • Exclude citizen ai from the government.
  • Given a newspaper article text, calculate how politicized it is. To do this, for every active government member the system counts the number of times his surname occurs in the text as a substring. All occurrences are taken into consideration, including the intersecting ones. The degree of politicization of a text is defined as the sum of these values for all active government members.

Implement this system.

Input

The first line contains space-separated integers n and k (1 ≤ n, k ≤ 105) — the number of queries to the system and the number of potential government members.

Next k lines contain the surnames a1, a2, ..., ak, one per line. All surnames are pairwise different.

Next n lines contain queries to the system, one per line. Each query consists of a character that determines an operation and the operation argument, written consecutively without a space.

Operation "include in the government" corresponds to the character "+", operation "exclude" corresponds to "-". An argument of those operations is an integer between 1 and k — the index of the citizen involved in the operation. Any citizen can be included and excluded from the government an arbitrary number of times in any order. Including in the government a citizen who is already there or excluding the citizen who isn't there changes nothing.

The operation "calculate politicization" corresponds to character "?". Its argument is a text.

All strings — surnames and texts — are non-empty sequences of lowercase Latin letters. The total length of all surnames doesn't exceed106, the total length of all texts doesn't exceed 106.

Output

For any "calculate politicization" operation print on a separate line the degree of the politicization of the given text. Print nothing for other operations.

Examples

input
7 3
a
aa
ab
?aaab
-2
?aaab
-3
?aaab
+2
?aabbaa

output

6
4
3
6

Solution

fail树的经典运用。

先建出fail树,然后用树状数组维护DFS序即可。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define MAXN 1000100
int K,N,loc[MAXN],visit[MAXN];
struct EdgeNode{int next,to;}edge[MAXN<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
char S[MAXN];
namespace FailTree
{
    int son[MAXN][27],end[MAXN],sz=1,fail[MAXN];
#define id(str) str-'a'+1
    inline int Insert(int x,char str[])
    {
        int len=strlen(str+1),now=1;
        for (int i=1; i<=len; i++)
            if (son[now][id(str[i])]) now=son[now][id(str[i])];
                else son[now][id(str[i])]=++sz,now=sz;
        end[now]=1; loc[x]=now;
    }
    queue<int>q;
    inline void Getfail()
    {
        q.push(1);
        while (!q.empty())
            {
                int now=q.front(); q.pop();
                for (int i=1; i<=26; i++)
                    if (son[now][i])
                        {
                            int fa=fail[now];
                            while (fa && !son[fa][i]) fa=fail[fa];
                            fail[son[now][i]]=fa? son[fa][i]:1;
                            q.push(son[now][i]);
                        }
            }
        for (int i=1; i<=sz; i++) InsertEdge(fail[i],i);
    }
}
using namespace FailTree;
namespace Divide
{
    int pl[MAXN],pr[MAXN],dfn,tree[MAXN<<1];
    inline void DFS(int now,int last)
    {
        pl[now]=++dfn;
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last)
                DFS(edge[i].to,now);
        pr[now]=++dfn;
    }
    inline int lowbit(int x) {return x&-x;}
    inline void Modify(int pos,int D) {for (int i=pos; i<=dfn; i+=lowbit(i)) tree[i]+=D;}
    inline int Query(int pos) {int re=0; for (int i=pos; i; i-=lowbit(i)) re+=tree[i]; return re;}
    inline int Calc(char str[])
    {
        int len=strlen(str+1),ans=0,now=1;
        for (int i=1; i<=len; i++)
            {
                while (now && !son[now][id(str[i])]) now=fail[now];
                now=now? son[now][id(str[i])]:1;
                ans+=Query(pl[now]);
            }
        return ans;
    }
    inline void Change(int x,int D)
    {
        if (visit[x] && D>0) return;
        if (!visit[x] && D<0) return;
        visit[x]^=1;
        Modify(pl[loc[x]],D); Modify(pr[loc[x]],-D);
    }
}
using namespace Divide;
int main()
{
    scanf("%d%d",&K,&N);
    for (int i=1; i<=N; i++) scanf("%s",S+1),Insert(i,S);
    Getfail(); DFS(1,0);
    for (int i=1; i<=N; i++) Modify(pl[loc[i]],1),Modify(pr[loc[i]],-1),visit[i]=1;
    while (K--)
        {
            char opt=getchar(); int x; 
            while (opt!='+' && opt!='-' && opt!='?') opt=getchar();
            switch (opt)
                {
                    case '+' : scanf("%d",&x); Change(x,1); break;
                    case '-' : scanf("%d",&x); Change(x,-1); break;
                    case '?' : scanf("%s",S+1); printf("%d\n",Calc(S)); break;
                }
        }
    return 0;
}

 

转载于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6146801.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
摘 要 伴随着人才教学的关注度越来越高,对于人才的培养也是当今社会发展的最为重要的问题之一。为了进一步的进行人才的培养关工作,许多的学校或者是教育的机构逐步的开展了网络信息化的教学和和管理工作,通过信息化的手段和技术实现网络信息化的教育及管理模式,通过网络信息化的手段实现在线答题在线考试和学生信息在线的管理等操作。这样更加的快捷解决了人才培养之中的问题,也在进一步的促进了网络信息化教学方式的快速的发展工作。相较于之前的人才教育和培养工作之中,存在这许多的问题和局限性。在学生信息管理方面通过线下管理的形式进行学生信息的管理工作,在此过程之中存在着一定的局限性和低效性,往往一些突发的问题导致其中工作出现错误。导致相关的教育工作受到了一定的阻碍。在学生信息和学生成绩的管理方面,往常的教育模式之下都是采用的是人工线下的进行管理和整理工作,在这一过程之中存在这一定的不安全和低效性,面对与学生基数的越来越大,学生的信息管理也在面领着巨大的挑战,管理人员面领着巨大的学生信息的信息量,运用之前的信息管理方式往往会在统计和登记上出现错误的情况的产生,为后续的管理工作造成了一定的困难。然而通过信息化的管理方式进行对学生信息的管理不仅可以避免这些错误情况的产生还可以进一步的简化学生信息管理工作的流程,节约了大量的人力和物力的之处。在线答题系统的实现不仅给学生的信息管理工作和在线考试带来了方便也进一步的促进了教育事业信息化的发展,从而实现高效化的教学工作。
引用\[1\]中提到了一种形动态规划的方法来解决CodeForces - 982C问题。在这个问题中,subtree指的是子连通块,而不是子。为了使cnt_white - cnt_black尽可能大,可以使用两次形动态规划来求解。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的链所代表的子。在第二次遍历中,需要维护一个sum变量,用于存储链所代表的子的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。如果ans\[u\]为正,则减去dp\[v\]就是链所代表的子的权值。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] 问题: CodeForces - 982C 形DP是什么问题?如何解决? 回答: CodeForces - 982C是一个形动态规划问题。在这个问题中,需要求解子连通块的最大权值和,使得cnt_white - cnt_black尽可能大。解决这个问题的方法是使用两次形动态规划。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的链所代表的子。在第二次遍历中,需要维护一个sum变量,用于存储链所代表的子的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] #### 引用[.reference_title] - *1* *2* [CodeForces - 1324F Maximum White Subtree(形dp)](https://blog.csdn.net/qq_45458915/article/details/104831678)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值