题目链接:http://codeforces.com/contest/710/problem/F

题意:维护一个集合,集合要求满足三种操作。 1 str:向集合插入字符串str(保证不会插入之前已经插入过的字符串) 2str:从集合中删除字符串str(保证删除的str一定在集合中) 3 str:str的子串有多少个在集合中出现过。

思路:题目意思就是一个可以插入/删除/查询的AC自动机。但是如果我们暴力求解,每次添加/删除一个字符串到自动机中求从前求一边适配指针的话会TLE。所以我们考虑用其他方法,设置一个恰当的阈值。如果小于这个阈值则把字符串放入trie树中,而大于阈值的直接保存下来。然后对于添加标记+1 ,删除标记-1。关于操作3把字符串分别与字典树的串匹配和保存下来的串匹配。关于在字典树的匹配。我们只需枚举str的所有后缀去匹配字典树即可。对于保存下来的串我们对其每一个建立KMP的next数组,然后就是普通的KMP的单模式匹配了。     用时不到1S

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<queue>
#include<math.h>
#include<time.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long int LL;
const int MAXN = + ;
const int CASE_SIZE = ;
const int S_SIZE = ;
const int B_SIZE = MAXN / S_SIZE + ;
struct Trie{
int child[MAXN][CASE_SIZE], value[MAXN],trieN,root;
void init(){
trieN = root = ; value[root] = ;
memset(child[root], -, sizeof(child[root]));
}
int newnode(){
trieN++; value[trieN] = ;
memset(child[trieN], -, sizeof(child[trieN]));
return trieN;
}
void insert(char *s,int val){
int x = root;
for (int i = ; s[i]; i++){
int d = s[i] - 'a';
if (child[x][d] == -){
child[x][d] = newnode();
}
x = child[x][d];
}
value[x] += val;
}
int search(char *s){
int sum = , x = root;
for (int i = ; s[i]; i++){
int d = s[i] - 'a';
if (child[x][d] == -){
break;
}
x = child[x][d];
sum += value[x];
}
return sum;
}
}trie;
struct KMP{
int Next[MAXN];
void getNext(string s,int len){
memset(Next, , sizeof(Next));
int i = , j = -; Next[] = -;
while (i < len){
if (j == - || s[i] == s[j]){
++i; ++j;
Next[i] = j;
}
else{
j = Next[j];
}
}
}
int search(string s,char *str){
int sum = , j = , lens = s.length(),lenstr=strlen(str);
getNext(s, s.length());
for (int i = ; i < lenstr; i++){
while (j> && s[j] != str[i]){
j = Next[j];
}
if (s[j] == str[i]){
j++;
}
if (j == lens){
sum++; j = Next[j];
}
}
return sum;
}
}kmp;
string Bstr[B_SIZE];
char str[MAXN];
int cnt, Bvalue[B_SIZE];
int main() {
int t, m,len,val;
while (~scanf("%d", &m)) {
trie.init(); cnt = ; memset(Bvalue, , sizeof(Bvalue));
for (int i = ; i <= m; i++){
scanf("%d%s", &t, str);
len = strlen(str);
if (t == || t == ){ //插入和删除
val = (t == ? : -); //插入=1,删除=-1
if (len <= S_SIZE){//小与阈值删除字典树
trie.insert(str, val);
}
else{ //大于阈值直接保存起来
Bstr[cnt] = string(str);
Bvalue[cnt++] = val; //标记是添加的还是删除的
}
}
else{ //查询
LL ans = ;
for (int i = ; i < len; i++){ //字典树上匹配
ans += trie.search(str + i);
}
for (int i = ; i < cnt; i++){ //暴力KMP匹配
if (Bstr[i].length() > len){ continue; }
ans += kmp.search(Bstr[i], str)*Bvalue[i];
}
printf("%I64d\n", ans);
fflush(stdout);
}
}
}
return ;
}

CodeForces 710F 强制在线AC自动机的更多相关文章

  1. CodeForces - 710F:String Set Queries (二进制分组 处理 在线AC自动机)

    ou should process m queries over a set D of strings. Each query is one of three kinds: Add a string ...

  2. hdu_4787_GRE Words Revenge(在线AC自动机)

    题目链接:hdu_4787_GRE Words Revenge 题意: 总共有n个操作,2种操作.每行读入一个字符串. 1.如果字符串以+开头,此为单词(即模式串,不考虑重复) 2.如果字符串以?开头 ...

  3. Codeforces 1015F Bracket Substring AC自动机 + dp

    Bracket Substring 这么垃圾的题怎么以前都不会写啊, 现在一眼怎么就会啊.... 考虑dp[ i ][ j ][ k ][ op ] 表示 已经填了 i 个空格, 末尾串匹配到 所给串 ...

  4. Codeforces 590E - Birthday(AC 自动机+Dilworth 定理+二分图匹配)

    题面传送门 AC 自动机有时只是辅助建图的工具,真的 首先看到多串问题,果断建出 AC 自动机.设 \(m=\sum|s_i|\). 不难发现子串的包含关系构成了一个偏序集,于是我们考虑转化为图论,若 ...

  5. Codeforces 1483F - Exam(AC 自动机)

    Codeforces 题目传送门 & 洛谷题目传送门 一道 ACAM 的 hot tea 首先建出 ACAM.考虑枚举长串,以及短串在长串中出现的最后位置 \(j\),这个复杂度显然是 \(\ ...

  6. Codeforces 696D Legen...(AC自动机 + 矩阵快速幂)

    题目大概说给几个字符串,每个字符串都有一个开心值,一个串如果包含一次这些字符串就加上对应的开心值,问长度n的串开心值最多可以是多少. POJ2778..复习下..太弱了都快不会做了.. 这个矩阵的乘法 ...

  7. 【AC自动机】背单词

    题意: 0 s v:添加价值为v的字符串s 1 t:查询t中含的s的权值和.(不停位置算多次) 思路: 在线AC自动机. 同学用过一个妙妙子的分块算法. 这里用二进制分组:通常用作把在线数据结构问题转 ...

  8. Codeforces 710F - String Set Queries(AC 自动机)

    题面传送门 题意:强制在线的 AC 自动机. \(n,\sum|s|\leq 3\times 10^5\) 如果不是强制在线那此题就是道 sb 题,加了强制在线就不那么 sb 了. 这里介绍两种做法: ...

  9. 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组

    F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...

随机推荐

  1. mybatis延迟加载

    配置完成后可能会报错Cannot enable lazy loading because CGLIB is not available. Add CGLIB to your classpath 是由于 ...

  2. CCF 节日

    问题描述 有一类节日的日期并不是固定的,而是以"a月的第b个星期c"的形式定下来的,比如说母亲节就定为每年的五月的第二个星期日. 现在,给你a,b,c和y1, y2(1850 ≤ ...

  3. asp.net 上一条和下一条记录的显示

    这里我用的是input标签跳转页面的: 前台aspx页面中: <input class="btn" id="btnSetForm" type=" ...

  4. 数据库IO简介

    IO有四种类型:连续读,随机读,随机写和连续写,连续读写的IO size通常比较大(128KB-1MB),主要衡量吞吐量,而随机读写的IO size比较小(小于8KB),主要衡量IOPS和响应时间.数 ...

  5. 比较原声socket 、GCDAsyncSocket

    原声socket NSInputStream 输入流(OC)NSOutputStream 输出流(OC)1:通过c语言的输入输出流CFReadStreamRef/CFWirteStreamRef(输入 ...

  6. 高效使用你的Xcode

    (via:VongLo's Dev Space  原文:Supercharging Your Xcode Efficiency)   好莱坞电影里经常看到黑客们手指在键盘上飞速跳跃,同时终端上的代码也 ...

  7. Android 菜单定制使用小结

    GridView 添加 ArrayAdapter<Bean>, 在 gridView 的 Item 点击之后, 1.list.add(bean)/remove(bean) 2.adapte ...

  8. 实现QQ在线咨询(需先添加好友)

    实现效果如图: 点击客服专员一.二.三之后提示添加qq好友,进行聊天. 代码如下: <div class="attachLeft"> <img src=" ...

  9. bootstratp图标的使用

    bootstratp作为一个优秀的前端框架,最近使用了其中的Glyphicon Halflings的字体图标.起初一直显示不出来,后面通过搜索相关资料直到成功显示,在此做一些总结,方便后面复习. 1. ...

  10. AIX性能监控

    http://www.ibm.com/developerworks/cn/aix/library/au-aix7memoryoptimize2/ http://www.aixchina.net/Art ...