点此看题面

大致题意: 给你\(N\)个单词,请你求出每一个单词在这\(N\)个单词中出现的次数。

相关题目

这道题应该是洛谷上一道板子题的升级版。

\(AC\)自动机

这是一道\(AC\)自动机的简单运用题。

题解

一个比较暴力的做法,就是将这\(N\)个单词建一棵\(Trie\),然后将每个单词一个一个分别去跑\(AC\)自动机,可惜这样子会\(TLE\)。

进一步的,我们可以发现,相同的单词跑\(AC\)自动机的结果是一样的,为什么不一起跑呢?

这样就可以\(AC\)了。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=ch:(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=ch))
#define N 200
#define SUM 1000000
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,rt=1,tot=1,ans,s[N+5];
string ss[N+5];
struct Trie
{
int Son[26],Next,Cnt,Vis;
}node[SUM+5];
queue<int> q;
inline void read(int &x)
{
x=0;static char ch;
while(!isdigit(ch=tc()));
while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
}
inline void read_string(string &x)
{
x="";static char ch;
while(isspace(ch=tc()));
while(x+=ch,!isspace(ch=tc())) if(!(~ch)) return;
}
inline void write(int x)
{
if(x>9) write(x/10);
pc(x%10+'0');
}
inline void Insert(int pos,string st)
{
register int i,nxt,x=rt,len=st.length();
for(i=0;i<len;++i)
{
if(!node[x].Son[nxt=st[i]-97]) node[x].Son[nxt]=++tot;
x=node[x].Son[nxt];
}
++node[x].Cnt,s[pos]=x;
}
inline void GetNext()
{
register int i,k;q.push(rt);
while(!q.empty())
{
k=q.front(),q.pop();
for(i=0;i<26;++i)
{
if(k^rt)
{
if(!node[k].Son[i]) node[k].Son[i]=node[node[k].Next].Son[i];
else node[node[k].Son[i]].Next=node[node[k].Next].Son[i],q.push(node[k].Son[i]);
}
else
{
if(!node[k].Son[i]) node[k].Son[i]=rt;
else node[node[k].Son[i]].Next=rt,q.push(node[k].Son[i]);
}
}
}
}
inline void AC_Automation(string st,int val)//将字符串st作为文本串跑AC自动机,并用val记录st的重复个数
{
register int i,j,x=rt,len=st.length();
for(i=0;i<len;++i)
{
if(!(x=node[x].Son[st[i]-97])) {x=rt;continue;}
int p=x;
while(p^rt) node[p].Vis+=val,p=node[p].Next;//记录这个节点被val个字符串访问过了
}
}
int main()
{
register int i,j;
for(read(n),i=1;i<=n;++i) read_string(ss[i]),Insert(i,ss[i]);
for(GetNext(),i=1;i<=n;++i)
if(~node[s[i]].Cnt) AC_Automation(ss[i],node[s[i]].Cnt),node[s[i]].Cnt=-1;//一次性将所有与当前字符串相同的字符串一起跑AC自动机,并标记当前字符串已经跑过,不然会TLE
for(i=1;i<=n;++i) write(node[s[i]].Vis),pc('\n');//输出每一个字符串在Trie上所对应的节点被访问的次数
return fwrite(pp,1,pp_,stdout),0;
}

【BZOJ3172】[TJOI2013] 单词(AC自动机的小应用)的更多相关文章

  1. BZOJ3172[Tjoi2013]单词——AC自动机(fail树)

    题目描述 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. 输入 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个 ...

  2. bzoj3172: [Tjoi2013]单词 ac自动机

    某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词 ...

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

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

  4. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

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

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

  6. [TJOI2013]单词 AC自动机

    题面: 洛谷 题解: 很久之前做的题了,只不过之前一直90....最近才发现是哪里写错了. 我们对字符集建AC自动机. 首先考虑一个暴力的做法,把文章当做一个长串,直接在自动机上跳,但是我们会发现,这 ...

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

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

  8. [TJOI2013]单词 AC 自动机

    题目描述: 小张最近在忙毕设,所以一直在读论文. 一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 题解: AC 自动机裸题,将所有字符串读入 ...

  9. 【BZOJ-3172】单词 AC自动机

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2567  Solved: 1200[Submit][Status ...

  10. 【BZOJ 3172】[Tjoi2013]单词 AC自动机

    关于AC自动机:一个在kmp与Trie的基础上建立的数据结构,关键在于Trie树结构与fail指针,他们各有各的应用.在AC自动机里最典型的就是多串匹配,原本效率为O(n*l+n*l+m*l),(n是 ...

随机推荐

  1. 2017BAPC初赛A(思维,无序图,向量)

    #include<bits/stdc++.h>using namespace std;string goods,sister[100010];int x,m;unordered_map&l ...

  2. (PHP)redis Set(集合)操作

    /** * * Set操作 * 集合命令 * 保证数据的唯一 * 不保证顺序 * */ //将一个元素加入集合,已经存在集合中的元素则忽略.若集合不存在则先创建,若key不是集合类型则返回false, ...

  3. jquery封装多棵并列树

    起因:当前的树都是在一棵树上,应产品需求,现在需要将一级菜单并列开,然后往下铺,这样只好自己写了. demo图: 我直接封在了jquery上,此外还加了获取勾选数据的一些简单API. 思路:先把一级菜 ...

  4. 树形DP 洛谷P2014 选课

    洛谷P2014 选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门 ...

  5. 2019南昌邀请赛网络赛:J distance on the tree

    1000ms 262144K   DSM(Data Structure Master) once learned about tree when he was preparing for NOIP(N ...

  6. php模拟post提交数据

    $data = '{ "id": "17999030", "method": "sayHello", "jso ...

  7. PAT甲级——1093 Count PAT's (逻辑类型的题目)

    本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/93389073 1093 Count PAT's (25 分)   ...

  8. Jmeter 线程组、运行次数参数化(转)Jpara1=4 -Jpara2=5

    Jmeter的jmx文件保存了线程数和运行次数等参数,这个参数可以在命令行中传入参数的方式来修改数值 步骤如下 1.生成线程和运行次数的参数 Jmeter选项中函数助手对话框,选中__P参数,这个参数 ...

  9. 源码分析Thread

    多次start ?? IlleageStateException

  10. linux高级编程基础系列:线程间通信

    linux高级编程基础系列:线程间通信 转载:原文地址http://blog.163.com/jimking_2010/blog/static/1716015352013102510748824/ 线 ...