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<<];
int head[MAXN],cnt=;
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][],end[MAXN],sz=,fail[MAXN];
#define id(str) str-'a'+1
inline int Insert(int x,char str[])
{
int len=strlen(str+),now=;
for (int i=; 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]=; loc[x]=now;
}
queue<int>q;
inline void Getfail()
{
q.push();
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=; i<=; 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]:;
q.push(son[now][i]);
}
}
for (int i=; i<=sz; i++) InsertEdge(fail[i],i);
}
}
using namespace FailTree;
namespace Divide
{
int pl[MAXN],pr[MAXN],dfn,tree[MAXN<<];
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=; for (int i=pos; i; i-=lowbit(i)) re+=tree[i]; return re;}
inline int Calc(char str[])
{
int len=strlen(str+),ans=,now=;
for (int i=; i<=len; i++)
{
while (now && !son[now][id(str[i])]) now=fail[now];
now=now? son[now][id(str[i])]:;
ans+=Query(pl[now]);
}
return ans;
}
inline void Change(int x,int D)
{
if (visit[x] && D>) return;
if (!visit[x] && D<) return;
visit[x]^=;
Modify(pl[loc[x]],D); Modify(pr[loc[x]],-D);
}
}
using namespace Divide;
int main()
{
scanf("%d%d",&K,&N);
for (int i=; i<=N; i++) scanf("%s",S+),Insert(i,S);
Getfail(); DFS(,);
for (int i=; i<=N; i++) Modify(pl[loc[i]],),Modify(pr[loc[i]],-),visit[i]=;
while (K--)
{
char opt=getchar(); int x;
while (opt!='+' && opt!='-' && opt!='?') opt=getchar();
switch (opt)
{
case '+' : scanf("%d",&x); Change(x,); break;
case '-' : scanf("%d",&x); Change(x,-); break;
case '?' : scanf("%s",S+); printf("%d\n",Calc(S)); break;
}
}
return ;
}

【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组的更多相关文章

  1. AC自动机fail树上dfs序建线段树+动态memset清空

    题意:http://acm.hdu.edu.cn/showproblem.php?pid=4117 思路:https://blog.csdn.net/u013306830/article/detail ...

  2. 2018.10.20 NOIP模拟 巧克力(trie树+dfs序+树状数组)

    传送门 好题啊. 考虑前面的32分,直接维护后缀trietrietrie树就行了. 如果#号不在字符串首? 只需要维护第一个#前面的字符串和最后一个#后面的字符串. 分开用两棵trie树并且维护第一棵 ...

  3. 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2022  Solved: 1158[Submit][Sta ...

  4. CodeForces - 1207G :Indie Album(AC自动机 fail树上DFS)

    题意:有N个串,给出的形式是拼接给出,对于第i行:  (1,c)表示字符串i是单个字母c: (2,p,c)表示字符串i=在字符串p后面接上一个字母c. 然后给出M个提问,形式是(i,string).问 ...

  5. bzoj2434 fail树 + dfs序 + 树状数组

    https://www.lydsy.com/JudgeOnline/problem.php?id=2434 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...

  6. CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)

    The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...

  7. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  8. 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  9. 【学习笔记】ac自动机&fail树

    定义 解决文本串和多个模式串匹配的问题: 本质是由多个模式串形成的一个字典树,由tie的意义知道:trie上的每一个节点都是一个模式串的前缀: 在trie上加入fail边,一个节点fail边指向这个节 ...

随机推荐

  1. 5.1 JS中Object类型

    1.Object类型是引用类型中的一种. 2.创建Object实例(对象)的方式: 方式1:使用new操作符,后面跟上Object构造函数.如: var obj = new Object();//创建 ...

  2. YYStock开源----iOS股票K线绘制第二版

    新的股票绘制粗来啦,欢迎围观star的说(*^__^*) 嘻嘻-- 捏合功能也准备完善了 Github:https://github.com/yate1996/YYStock 长按分时图+五档图 分时 ...

  3. iOS NSNotificationCenter详解

    通知中心的特点: 1:同步执行 2: 一对多发送消息 3: 降低程序耦合度 通知中心是单例,目的就是从任意一个发送消息到任意一个接收者,是同步执行的. 那么什么是同步呢? 用网上经典的说法,就是我叫朋 ...

  4. ASP.NET MVC 3 网站优化总结(六)压缩 HTML

    压缩 html 可以去除代码中无用的空格等,这样可提高网站的加载速度并节省带宽.今天就让我们看看在 ASP.NET MVC 3 怎么实现 html 压缩,我们可通过实现 ActionFilter 来完 ...

  5. vim使用笔记

    vim的配置文件.vimrc  一般有2个位置 1是在/目录下 2是在-目录下 如果在-目录下有了配置文件 那么将不去读取/目录下面的配置文件 如果你不知道现在使用的vim 使用的是哪个目录下面的配置 ...

  6. C#学习

    C#开发轻松入门(慕课网)1.C#简介 1-1 .NET简介 .NET平台可运用多种语言编程,C#配合的最好. 1-2 Visual Studio简介及安装 ... 1-6 Hello World 控 ...

  7. [笔记]linux磁盘管理

    sudo mount -r /dev/sda3 /mnt/vista 只读挂载 sudo umount sudo umount -r 无法卸载时只读重新挂载 mount -t(指明设备类型) 可用参数 ...

  8. error LNK2001: 无法解析的外部符号

    1.错误描述 error LNK2001: 无法解析的外部符号 "__declspec(dllimport) void __cdecl PadSystem::Private::printQS ...

  9. Android ListView ArrayAdapter 的简单使用

    前面写了3篇关于android的文章,其中的演示程序都写在了一个工程中,当时为了方便测试就在启动页MainActivity中放了3个按钮,点击不同的按钮进入不同的示例程序页面,MainActivity ...

  10. SCNU 2015ACM新生赛初赛【1007. ZLM的扑克牌】解题报告

            题目链接详见SCNU 2015新生网络赛 1007. ZLM的扑克牌 .         其实我在想这题的时候,还想过要不要设置求最小的排列,并且对于回文数字的话,可以把扑克牌折起来( ...