点此看题面

大致题意: 给你\(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. PAT L2-006【二叉树中序后序构造树】

    #include<bits/stdc++.h> using namespace std; typedef long long LL; struct BT{ int w; BT *L; BT ...

  2. 初等变换求 |A| % Mod & A- % Mod & A* % Mod(模板)

    // |A| * A- = A* (伴随矩阵) = 逆矩阵 * 矩阵的值 #include<cstdio> #include<cstring> #include<cstd ...

  3. java整理(一)

    1.方法重载:方法名称相同,参数的类型或个数不同.但是返回值类型不同,不是方法重载. 2.引用数据类型:数组,类,接口.内存地址分为两类,栈内存和对内存.栈内存保存的是对内存的地址,简单理解就是保存了 ...

  4. KSOAP2使用注意点汇总

    注意返回类型,如果是XML格式,使用 1:SoapObject soapObject = (SoapObject) envelope.getResponse(); 2:SoapObject resul ...

  5. ios开发 xcode6以上安装Alcatraz管理插件

    在终端上输入如下命令即可完成安装: curl -fsSL https://raw.github.com/supermarin/Alcatraz/master/Scripts/install.sh |  ...

  6. List、Set

    List.Set List.Set List.Set List.Set List.Set List.Set List.Set

  7. js 为对象添加和删除属性

    对于一个普通的js对象: var obj = { name:"mary", age:21 } 如果我们要对它添加新属性的话可以使用下列方式: obj.address = " ...

  8. Sharepoint 图片库字段名称(Title)和对应的内部名称(InternalName)

    做项目遇到需要查看列表库的内部名称,因为用的是图片库,所以就列出所有对应关系,以备查看方便:

  9. mysql CPU占用高

    https://blog.csdn.net/u011239989/article/details/72863333 QPS高,sql简单的场景下, 需要 1. 提高数据库的服务器性能CPU 内存等 2 ...

  10. Scrapy(爬虫应用框架)安装配置

    运行平台:Windows Python版本:Python3.x 一.Scarpy 简介 Scrapy是一个为了爬取网站数据提取结构性数据而编写的应用框架,可以应用于数据挖掘,信息处理或存储历史数据等一 ...