E. e-Government

题目:

  给出n个字符串,表示n个人名,有两种操作:

  ?string ,统计字符串string中出现的属于城市居民的次数。

  +id,把编号为id的人变为城市居民,如果已经是忽略。

  -id,把编号为id的人变为不是城市居民,如果已经不是的话忽略。

  现有m个操作,对于?输出结果。

分析:

  很容易想到建立ac自动机,+-操作倒简单,使用bool数组标记一下即可。对于每个询问,每次都沿着fail指针往上走,遇到了标记为城市居民的字符串时加1,否则继续往上走。

  在这显然会TLE。很容易构造出以下数据:

  a

  aa

  aaa

  ...

  aaa...aaa

  ?aaa...aaa

  

  考虑把fail指针反向,由于ac自动机的每个节点均有唯一的fail指针,若是沿着fail指针往上走,显然都会走到root,所以反向之后显然是一棵树,不妨称之为fail树。

  fail树有什么特点呢?可以画个图试试,如果儿子节点出现过,那么他的祖先显然也会出现!因此,我们统计某个节点时,实际上就是统计在fail树中该节点到根的所有节点出现过的总次数。怎么统计?这不就是用dfs序维护树状数组吗?于是这题得以解决。每次寻找的时间复杂度为O(len*log)的级别。

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull; #define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int>
#define PQ priority_queue
#define cmax(x,y) x = max(x,y)
#define cmin(x,y) x = min(x,y)
#define Clear(x) memset(x,0,sizeof(x))
//#pragma comment(linker, "/STACK:1024000000,1024000000") /******** program ********************/ const int MAXN = 1.5e6;
const int kind = 26; char s[MAXN];
bool use[MAXN]; struct BIT{
int c[2*MAXN];
inline void init(){
Clear(c);
}
inline int lowbit(int x){
return x & -x;
}
inline void update(int x,int y,int val){
modify(x,val);
modify(y,-val);
}
inline void modify(int x,int val){
if(x==0)return;
while(x<MAXN){
c[x] += val;
x += lowbit(x);
}
}
inline int ask(int x){
int ans = 0;
while(x>0){
ans += c[x];
x -= lowbit(x);
}
return ans;
}
}bit; struct AC{
int ch[MAXN][kind],fail[MAXN];
int tot;
vector<int> adj[MAXN];
int low[MAXN],dfn[MAXN],tol;
int at[MAXN]; inline void set(int x){
Clear(ch[x]);
fail[x] = 0;
} inline void init(){
rep(i,MAXN)
adj[i].clear();
set(1);
tot = 1;
tol = 0;
} inline int newNode(){
set(++tot);
return tot;
} inline int ind(char c){
return c-'a';
} inline void insert(int id){
int r = 1;
for(int i=0;s[i];i++){
int c = ind(s[i]);
if(ch[r][c]==0)
ch[r][c] = newNode();
r = ch[r][c];
}
at[id] = r;
} inline void build(){
queue<int> q;
q.push(1);
while(!q.empty()){
int r = q.front();
q.pop();
if(fail[r])
adj[ fail[r] ].pb(r);
rep(c,kind){
int x = ch[r][c];
if(!x)continue;
q.push(x); int y = fail[r];
while(y&&ch[y][c]==0)
y = fail[y];
fail[x] = y?ch[y][c]:1;
}
}
} void dfs(int x){
low[x] = ++tol;
foreach(i,adj[x])
dfs(adj[x][i]);
dfn[x] = tol;
} inline void run(){
int len = strlen(s)-1;
int ans = 0; int r = 1;
rep1(i,len){
int c = ind(s[i]);
while(r&&ch[r][c]==0)
r = fail[r];
if(r) r = ch[r][c];
else r = 1;
ans += bit.ask( low[r] );
} printf("%d\n",ans);
} }ac; void cc(int x,int val){
bit.update( ac.low[ ac.at[x] ],1+ac.dfn[ ac.at[x] ],val );
} int main(){ #ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif int n,m;
while(cin>>m>>n){
ac.init();
bit.init(); rep1(i,n){
scanf("%s",s);
ac.insert(i);
use[i] = true;
} ac.build();
ac.dfs(1); rep1(x,n)
cc(x,1); int x;
while(m--){
scanf("%s",s);
if(s[0]=='?')
ac.run();
else{
sscanf(s+1,"%d",&x);
if(use[x]&&s[0]=='-'){
use[x] = 0;
cc(x,-1);
}else if(!use[x]&&s[0]=='+'){
use[x] = 1;
cc(x,1);
}
}
}
} return 0;
}

  

CF 163E. e-Government ac自动机+fail树+树状数组的更多相关文章

  1. CF G. Indie Album AC自动机+fail树+线段树

    这个套路挺有意思的. 把 $trie$ 和 $fail$ 树都建出来,然后一起跑一跑就好了~ #include <queue> #include <cstdio> #inclu ...

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

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

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

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

  4. AC自动机——1 Trie树(字典树)介绍

    AC自动机——1 Trie树(字典树)介绍 2013年10月15日 23:56:45 阅读数:2375 之前,我们介绍了Kmp算法,其实,他就是一种单模式匹配.当要检查一篇文章中是否有某些敏感词,这其 ...

  5. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

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

  6. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  7. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

  8. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

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

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

随机推荐

  1. 通过css代码使边框变圆角(ie9以下浏览器不支持)

    (从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期2014-02-11) CSS代码: <style> #myDiv { border-radius: 4px; /*这句就是 ...

  2. XHTML编码规范

    1.所有的标记都要有结束标记. 2.所有标记的名称和属性名称都必须使用小写 3.所有的的标记必须合理嵌套 4.属性值必须用引号包含起来 5.需要设置的属性都要给一个值 XHTML 规定所有属性都必须有 ...

  3. WPF中的数据模板(DataTemplate)(转)

    原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/30/694388.html WPF中的数据模板(DataTemplate)        ...

  4. c# 轻量级ORM框架 实现(一)

    发布一个自己写的一个轻量级ORM框架,本框架设计期初基于三层架构.所以从命名上来看,了解三层的朋友会很好理解. 设计该框架的目的:不想重复的写增删改查,把精力放到功能实现上. 发布改框架的原因:希望给 ...

  5. oracle存储过程实例

    oracle存储过程实例 分类: 数据(仓)库及处理 2010-05-03 17:15 1055人阅读 评论(2)收藏 举报 认识存储过程和函数 存储过程和函数也是一种PL/SQL块,是存入数据库的P ...

  6. GridView 编辑修改

    //点击gridview控件自带的编辑按钮时执行的事件    protected void gvNewsList_RowEditing(object sender, GridViewEditEvent ...

  7. 使用Underscore.js的template将Backbone.js的js代码和html代码分离

    这段时间在学习Require.js和Backbone.js的过程中,发现有些项目里的HTML代码都是写在View的js代码里面的,渲染的时候需要对Collection进行循环,再将HTML代码拼接上去 ...

  8. 4K加速普及,8K近在咫尺,下一个是?

        从铺天盖地的厂商宣传到亲戚朋友家的客厅.不可否认4K时代已全面到来------业内人士估计2015年是4K电视的一个突破年.知名市场调查机构StrategyAnalytics对4K电视进行了调 ...

  9. mysql 升级方法

    Performing an In-place Upgrade This section describes how to perform an in-place upgrade. Review Bef ...

  10. WCF关于VS2010的配置

    C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE 下的 devenv.exe.config 在 <configura ...