P3966 [TJOI2013] 单词

对所有模式串建立AC自动机。

用\(p[i]\)来表示经过节点\(i\)的字符串个数。

那么节点\(u\)的答案就是fail树上,以\(u\)为根的子树的\(p\)之和。

由于我们已经计算了\(p[i]\),所以字符串\(i\)作为模式串本身&模式串前缀的情况已经考虑了。还需考虑\(i\)作为模式串后缀的情况,而只有fail树上子树\(i\)的节点才有\(i\)这个后缀,所以子树\(i\)的\(p\)之和就是节点\(i\)的答案。用拓扑排序一路更新到根节点即可。

点击查看代码
#include<bits/stdc++.h>
#define T 210
#define N 1000010
#define S 26
using namespace std;
int n,tr[N][S],fail[N],cnt,ans[N],pos[T],deg[N];
queue<int> q;
string s;
void ins(string s,int num){
int p=0;
for(char i:s){
int c=i-'a';
if(!tr[p][c]) tr[p][c]=++cnt;
p=tr[p][c];
ans[p]++;
}
pos[num]=p;
}
void get_fail(){
for(int i=0;i<26;i++)
if(tr[0][i]) q.push(tr[0][i]);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
if(tr[u][i])
fail[tr[u][i]]=tr[fail[u]][i],
q.push(tr[u][i]),deg[fail[tr[u][i]]]++;
else tr[u][i]=tr[fail[u]][i];
}
}
}
void topo(){
for(int i=1;i<=cnt;i++) if(!deg[i]) q.push(i);
while(!q.empty()){
int t=q.front();
q.pop();
ans[fail[t]]+=ans[t],deg[fail[t]]--;
if(!deg[fail[t]]) q.push(fail[t]);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>s;
ins(s,i);
}
get_fail();
topo();
for(int i=1;i<=n;i++)
cout<<ans[pos[i]]<<"\n";
return 0;
}

还有一种方法可以不用拓扑排序,就是用数组来模拟get_fail()中的队列,这样队头到队尾一定是BFS序,所以反过来,从队尾到队头一定是一个拓扑序,所以更新的时候不用拓扑排序,仅需用一个循环,从队尾遍历到队头,更新答案即可。

点击查看代码
#include<bits/stdc++.h>
#define T 210
#define N 1000010
#define S 26
using namespace std;
int n,tr[N][S],fail[N],cnt,ans[N],pos[T],q[N];
string s;
void ins(string s,int num){
int p=0;
for(char i:s){
int c=i-'a';
if(!tr[p][c]) tr[p][c]=++cnt;
p=tr[p][c];
ans[p]++;
}
pos[num]=p;
}
void get_fail(){
int head=1,tail=0;
for(int i=0;i<26;i++)
if(tr[0][i]) q[++tail]=tr[0][i];
while(head<=tail){
int u=q[head++];
for(int i=0;i<26;i++){
if(tr[u][i])
fail[tr[u][i]]=tr[fail[u]][i],
q[++tail]=tr[u][i];
else tr[u][i]=tr[fail[u]][i];
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>s;
ins(s,i);
}
get_fail();
for(int i=cnt;i>=1;i--) ans[fail[q[i]]]+=ans[q[i]];
for(int i=1;i<=n;i++)
cout<<ans[pos[i]]<<"\n";
return 0;
}

[题解]P3966 [TJOI2013] 单词的更多相关文章

  1. 洛谷P3966 [TJOI2013]单词(fail树性质)

    P3966 [TJOI2013]单词 题目链接:https://www.luogu.org/problemnew/show/P3966 题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单 ...

  2. P3966 [TJOI2013]单词

    P3966 [TJOI2013]单词 题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出 ...

  3. 洛谷P3966 [TJOI2013]单词(后缀自动机)

    传送门 统计单词出现次数……为啥大家都是写AC自动机的嘞……明明后缀自动机也能做的说…… 统计出现次数这个就直接按长度排序然后做个dp就好,这是SAM的板子的要求啊,不提了 然后考虑怎么让所有串之间隔 ...

  4. 洛谷P3966 [TJOI2013]单词(AC自动机)

    题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出格式 输入格式: 第一行一个整数N,表 ...

  5. [洛谷P3966][TJOI2013]单词

    题目大意:有$n$个字符串,求每个字符串在所有字符串中出现的次数 题解:$AC$自动机,每个节点被经过时$sz$加一,每一个字符串出现次数为其$fail$树子树$sz$和 卡点:$AC$自动机根节点为 ...

  6. Luogu P3966 [TJOI2013]单词

    题目链接 \(Click\) \(Here\) 本题\(AC\)自动机写法的正解之一是\(Fail\)树上跑\(DP\). \(AC\)自动机是\(Trie\)树和\(Fail\)树共存的结构,前者可 ...

  7. 【洛谷】3966:[TJOI2013]单词【AC自动机】【fail树】

    P3966 [TJOI2013]单词 题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出 ...

  8. 【BZOJ3172】[Tjoi2013]单词 AC自动机

    [BZOJ3172][Tjoi2013]单词 Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input ...

  9. [TJOI2013]单词

    2755: [TJOI2013]单词 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 6  Solved: 3[Submit][Status][Web B ...

  10. bzoj 3172: [Tjoi2013]单词 AC自动机

    3172: [Tjoi2013]单词 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

随机推荐

  1. maven导入org.apache.pdfbox

    PDF和图片相互转换用到的maven依赖如下: <dependency> <groupId>org.apache.pdfbox</groupId> <arti ...

  2. redis-cli 使用lua脚本笔记

    前言 众所周知,redis可以执行lua脚本,至于为什么要用lua脚本来操作redis,自行百度咯 先来讲一下最简单的方式, 关于如何在java springboot里用lua脚本,请查看我另一篇文章 ...

  3. html file input onchage没有调用(两次选择同一个文件)

    在html中,如果input的类型是file,且第二次选择的文件与第一次相同,那么onchange事件不会调用. 如果想调用,需要将event.target.value设置为null,如下: 原生写法 ...

  4. 江铃晶马 X 袋鼠云:搭建企业级数据资产中心,推进打造“智数晶马”

    江铃集团晶马汽车有限公司(简称:晶马汽车)系江铃集团全资子公司,属集团六大整车企业之一.晶马汽车是以大.中.轻型客车(含新能源客车).乘用车(不含轿车).专用车等车型研发.生产.销售和服务为核心的整车 ...

  5. UFT send request & get response

    str 为发出去的request :

  6. java 获取访问的真实ip

    request 是 javax.servlet.http.HttpServletRequest 获取其他机器访问自己服务时的真实ip public String getIP(HttpServletRe ...

  7. C# dataTable 操作 上移 下移

    https://blog.csdn.net/CSDN2016DDDD/article/details/80226755 上移:DataRow newdata = dt.NewRow();newdata ...

  8. C# ToolStripStatusLabel中没有 DataBindings

    https://social.msdn.microsoft.com/forums/windows/en-US/73de165c-e948-4015-bdcd-570f55a6e365/databind ...

  9. layui.laytpl如何从外部引入模板文件

    首页 index.html <body> <div id="hello"></div> <script src="./lib/l ...

  10. 卷积神经网络(LeNet)

    博客地址:https://www.cnblogs.com/zylyehuo/ 一.导入所用库 import torch from torch import nn from d2l import tor ...