题目链接: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一对多查询

    18 <!-- 19 方式一:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集 20 封装联表查询的数据(去除重复的数据) 21 select * from class c, teacher ...

  2. 决绝Capturing 'demo' strongly in this block is likely to lead to a retain cycle

    - (IBAction)onTest:(id)sender { BlockDemo *demo = [[BlockDemo alloc]init];  __weak typeof(BlockDemo) ...

  3. centos7 php7 httpd

    安装php之前,要先安装几个 1.下载php源码:http://cn2.php.net/distributions/php-7.0.6.tar.gz. 2.然后使用命令:tar -zxvf php-7 ...

  4. iphone删除自动更新的系统

    1.利用 etc/host 文件屏蔽 Apple 更新服务器用电脑 iTools 或者手机 iFile 打开 etc/host 文件,添加:127.0.0.1 mesu.apple.com到文件中.2 ...

  5. stm32——NFC芯片--PN532的使用

    stm32——NFC芯片--PN532的使用 一.NFC简介 NFC(Near Field Communication)近场通信,是一种短距高频的无线电技术,在13.56MHz频率运行于20厘米距离内 ...

  6. DB2 Z/os Load utility 使用

    Use the LOAD online utility to load one or more tables of a table space. The LOAD utility loads reco ...

  7. NYOJ题目768移位密码

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtIAAAJqCAIAAACJkTDlAAAgAElEQVR4nO3du3Ljvpa34b4J574Qx7

  8. 大话数据结构–1.基础知识+2.算法

      2.算法: 算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每个指令表现为一个或多个操作. 特性:输入.输出.有穷性.确定性.可行性.   2.9.1.算法时间复杂度: 语句 ...

  9. C#的反射机制

    using System; using System.Collections; using System.Collections.Generic; using System.IO; using Sys ...

  10. C#值类型与引用类型

    值类型(Value Type),值类型实例通常分配在线程的堆栈(stack)上,并且不包含任何指向实例数据的指针,因为变量本身就包含了其实例数据.其在MSDN的定义为值类型直接包含它们的数据,值类型的 ...