题目链接: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. bootstrap-datepicker的使用

    转载自:http://michael-roshen.iteye.com/blog/1779541 在普通的网页中显示datepicker比较简单,将bootstrap-datepicker-zh_CN ...

  2. LeetCode 283 Move Zeros

    Problem: Given an array nums, write a function to move all 0's to the end of it while maintaining th ...

  3. app上传到app Store常见问题

    一.首先看一下提交界面出现的问题(能成功打包成.ipa) 产生问题的原因如下:由于工程中含有sub project,而sub project中有private或public的文件导致的.这样的应用往往 ...

  4. 控制器与xib关联(用xib布局控制器)

    IOS Xib使用——为控制器添加Xib文件 Xib文件是一个轻量级的用来描述局部界面的文件,它与StoryBoard类似,都是使用Interface Bulider工具进行编辑.但是StoryBoa ...

  5. 无根树转有根树(dfs,tree)

    #include <bits/stdc++.h> #include <iostream> #include <queue> #include <stdio.h ...

  6. 浅析 - 提高xib(Interface Builder)高效工作的几个小技巧

    本文译自:8 Tips for working effectively with Interface Builder(需FQ)先来看看目录:介绍使view的Size与view中的Content相适应按 ...

  7. UISplitViewController - iPad分屏视图控制器

    UISplitViewController - 分屏视图控制器 概述 UISplitViewController 是一个容器vc, 展示一个 master-detail(主-详(从))界面. 主视图改 ...

  8. 解决passwd 为普通用户设密码 不成功的方法

    echo "xxxxxxxxx"|passwd --stdin user_name #这样设置密码就可以成功!

  9. Redis不同数据类型的的数据结构实现

    我们知道Redis支持五种数据类型, 分别是字符串.哈希表(map).列表(list).集合(set)和有序集合,和Java的集合框架类似,不同数据类型的数据结构实也是不一样的. >>Re ...

  10. VS使用技巧(转)

    转自http://www.cnblogs.com/xpvincent/p/3596553.html i. Ctrl-M-O 折叠所有方法 ii. Ctrl-M-P 展开所有方法并停止大纲显示(不可以再 ...