• 题意:

    0 s v:添加价值为v的字符串s

    1 t:查询t中含的s的权值和。(不停位置算多次)
  • 思路:

    在线AC自动机。

    同学用过一个妙妙子的分块算法。

    这里用二进制分组:通常用作把在线数据结构问题转离线

    即当前有n个串。然后按n的二进制分成(\(<=log_2n\))个AC自动机分别维护答案。

    e.g \(n=7(111)_2\)

    此时会有三个AC自动机,分别表示串[1,4],[5,6],[7,7]个数(sz[])分别为\(2^2,2^1,2^0\)

    查询也so easy.就每局每个自动机,在上面查找。最多查\(log_2n\)次。

    修改,每次加入一个串,先建一个只包含它本身sz[]=1的自动机。

    这里我们用stack维护每个自动机信息。

    然后如果最后一个自动机与前一个sz相等。把后两个自动机合并。

    因为每个串最多被合并\(log_2(s的个数m)\)次。然后复杂度是\(O(\sum|S|log_2(m)26)\)
  • code:

    细节mx_nd[i]表示第i个自动机的最大(最近添加)节点(因为节点是连续加入的)。

    每次删除st[tp]时,把节点数nd也回溯到mx_nd[tp-2](过程中清空删的节点),然后再合并st[tp-1]与st[tp]

    这样的好处是,空间是线性的。而且这么写常数也很小。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
int va[N],sz[N],tp,rt[N],fail[N],go[N][27],nd,len,head[N],L[N],stot,mx_nd[N];
ll val[N],lans;
int s[N];
char ch[N];
void Insert(int u,int l,int r,int w) {
for(int i=l;i<=r;i++) {
int x=s[i];
if(!go[u][x])go[u][x]=++nd;
u=go[u][x];
}
val[u]+=w;
}
int Q[N],hd,tl;
void gt_fail(int root) {
// printf("!%d\n",root);
hd=1,tl=0;
for(int i=0;i<26;i++) {
if(go[root][i]) fail[go[root][i]]=root,Q[++tl]=go[root][i];
else go[root][i]=root;
}
while(hd<=tl) {
int u=Q[hd++];val[u]+=val[fail[u]];
for(int i=0;i<26;i++) {
if(go[u][i]) fail[go[u][i]]=go[fail[u]][i],Q[++tl]=go[u][i];
else go[u][i]=go[fail[u]][i];
}
}
} void _Pass() {
while(tp>1&&sz[tp]==sz[tp-1]) {
int tmp=nd;nd=mx_nd[tp-2];
while(tmp>nd) {val[tmp]=fail[tmp]=0;for(int i=0;i<26;i++)go[tmp][i]=0;tmp--;}
tp--;sz[tp]*=2;rt[tp]=++nd;
for(int i=stot;i>=L[tp];i--) Insert(rt[tp],head[i],i==stot?len:head[i+1]-1,va[i]);
gt_fail(rt[tp]);mx_nd[tp]=nd;
}
}
void Query() {
int ln=strlen(ch);
lans=0;
for(int i=1;i<=tp;i++) {
int u=rt[i];
for(int j=0;j<ln;j++) {
int x=ch[j]-'a';
u=go[u][x];lans+=val[u];
// printf("!%c %d %lld\n",ch[j],u,lans);
}
}
printf("%lld\n",lans);
}
int main() {
int n,Type;
scanf("%d%d",&n,&Type);
for(int i=1;i<=n;i++) {
int opt,x;scanf("%d",&opt);
if(!opt) {
head[++stot]=len+1;
scanf("%s%d",ch,&va[stot]);
int ln=strlen(ch);
for(int j=0;j<ln;j++)s[++len]=Type?((ll)(ch[j]-'a')^lans)%26:ch[j]-'a';
rt[++tp]=++nd;sz[tp]=1;L[tp]=stot;
Insert(rt[tp],head[stot],len,va[stot]);mx_nd[tp]=nd;gt_fail(rt[tp]);
_Pass();
}
else {
scanf("%s",ch);
int ln=strlen(ch);
if(Type)for(int j=0;j<ln;j++) ch[j]=((ll)(ch[j]-'a')^lans)%26+'a';
Query();
}
}
return 0;
}

【AC自动机】背单词的更多相关文章

  1. 【AC自动机】单词

    [题目链接] https://loj.ac/problem/10060 [题意] 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. ...

  2. AC日记——背单词 洛谷 P2353

    背单词 思路: KMP+统计前缀和优化: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1000005 ], ...

  3. HDU - 6096 :String (AC自动机,已知前后缀,匹配单词,弱数据)

    Bob has a dictionary with N words in it. Now there is a list of words in which the middle part of th ...

  4. 【学时总结&模板时间】◆学时·10 & 模板·3◆ AC自动机

    ◇学时·10 & 模板·3◇ AC自动机 跟着高中上课……讲AC自动机的扩展运用.然而连KMP.trie字典树都不怎么会用的我一脸懵逼<(_ _)> 花一上午自学了一下AC自动机 ...

  5. 「HNOI2004」「LuoguP2292」L语言(AC自动机

    题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...

  6. 背单词(AC自动机+线段树+dp+dfs序)

    G. 背单词 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较   题目描述 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使 ...

  7. BZOJ2905: 背单词 AC自动机+fail树+线段树

    $zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...

  8. BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树

    Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...

  9. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. python-使用函数求特殊a串数列和

    给定两个均不超过9的正整数a和n,要求编写函数fn(a,n) 求a+aa+aaa++⋯+aa⋯aa(n个a)之和,fn须返回的是数列和 函数接口定义: 1 fn(a,n) 2 其中 a 和 n 都是用 ...

  2. sql server总结二

    一些常用查询 Insert into 表(字段一,字段二,字段三,---) values(插入一,插入二,插入三,----) Update 表 set 字段= where 字段= Delete fro ...

  3. Factorials and Powers of Two

    分析:我们可以看出这道题目的描述并不是很复杂,就是说对于一个给定的整数n,我们能否把他拆成k个powerful的数,也就是说这k个数要么是2的幂次,要么是某个数的阶乘,并且我们要让当前的k越小越好:然 ...

  4. [转]Fabric2.3中使用test-network搭建测试网络

    这个测试网络一方面可以用来学习Fabric,另一方面也可以让一些更有经验的开发者来测试他们的智能合约和应用,但是不建议用于生产环境,在2.0版本后,这个测试网络也取代了原来的"first-n ...

  5. paramterType和resultType的区别

    resultType是sql语句查询结果集的封装类型,也就是说把sql查询的结果封装在bean里返回回去,是存数据用的. paramType是从传过来的Bean中取数据放进例如insert语句的val ...

  6. Java基础语法01——变量与运算符

    本文是对Java基础语法的第一部分的学习,包括注释:标识符的命名规则与规范:变量的数据类型分类以及转换:以及六种运算符(算术.赋值.比较.逻辑.三元和位运算符).

  7. Nuxt 的介绍与安装

    Nuxt.js(一.介绍与安装) 1.为什么使用Nuxt 渐进式Vue.js框架给前后端分离带来无限的乐趣,越来越多的程序员选择Vue.在我们使用Vue框架的过程中不免会出现以下的一些问题: 如何更好 ...

  8. Java语言学习day26--7月01日

    ###14内部类 * A: 内部类的概述 将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类. 其他类也称为外部类. * B: 什么时候使用内部类 在描述事物 ...

  9. 手把手教会将 Windows 窗体桌面应用从.NET Framework迁移到 .NET SDK/.NET 6 格式

    接上篇:手把手教会 VS2022 设计 Winform 高DPI兼容程序 (net461 net6.0 双出) https://www.cnblogs.com/densen2014/p/1614293 ...

  10. k8s入门之Deployment(五)

    Deployment控制器通常用来部署无状态的应用,这样可以在任意的节点上扩容或者删除,而不用考虑数据的问题,它可以管理pod对象. 一.多副本 1.使用命令行方式创建Deployment 在dev名 ...