BZOJ_3172_[Tjoi2013]单词_后缀自动机
BZOJ_3172_[Tjoi2013]单词_后缀自动机
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
a
aa
aaa
Sample Output
3
1
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000050
int ch[N<<1][26],fa[N<<1],dep[N<<1],cnt=1,lst,n,flg[N];
int ws[N<<1],a[N<<1],siz[N<<1];
char w[N];
void insert(int x) {
int p=lst,np,q,nq;
if(ch[p][x]) {
q=ch[p][x];
if(dep[q]==dep[p]+1) lst=q;
else {
fa[nq=++cnt]=fa[q]; lst=nq;
dep[nq]=dep[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[q]=nq;
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}else {
np=++cnt; lst=np; dep[np]=dep[p]+1;
for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if(!p) fa[np]=1;
else {
q=ch[p][x];
if(dep[q]==dep[p]+1) fa[np]=q;
else {
fa[nq=++cnt]=fa[q];
dep[nq]=dep[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[q]=fa[np]=nq;
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}
}
}
int main() {
scanf("%d",&n);
int i,j;
for(i=1;i<=n;i++) {
scanf("%s",w+1);
lst=1;
for(j=1;w[j];j++) insert(w[j]-'a'),siz[lst]++;
flg[i]=lst;
}
for(i=1;i<=cnt;i++) ws[dep[i]]++;
for(i=1;i<=cnt;i++) ws[i]+=ws[i-1];
for(i=cnt;i;i--) a[ws[dep[i]]--]=i;
for(i=cnt;i;i--) {
int p=a[i];
siz[fa[p]]+=siz[p];
}
for(i=1;i<=n;i++) {
printf("%d\n",siz[flg[i]]);
}
}
方法2:注意每个串对应的结点不一定是一开始插入的那个结点。
需要每次找一遍,比较麻烦。
代码:
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 2000050
int ch[N<<1][27],fa[N<<1],dep[N<<1],cnt=1,lst=1,n,flg[N];
int ws[N<<1],a[N<<1],siz[N<<1],l[233],r[233];
char w[N],s[N];
void insert(int x) {
int p=lst,np=++cnt,q,nq;
lst=np; dep[np]=dep[p]+1;
for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if(!p) fa[np]=1;
else {
q=ch[p][x];
if(dep[q]==dep[p]+1) fa[np]=q;
else {
fa[nq=++cnt]=fa[q];
dep[nq]=dep[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[q]=fa[np]=nq;
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}
}
void print() {
int i,j;
printf("test-------------------------------------------\n");
for(i=1;i<=cnt;i++) {
printf("p=%d,siz=%d,dep=%d,fa=%d\n",i,siz[i],dep[i],fa[i]);
for(j=0;j<=26;j++) {
if(ch[i][j]) {
printf("ch(%d)(%c)=%d\n",i,j+'a',ch[i][j]);
}
}
}
printf("lst=%d\n",lst);
}
int main() {
scanf("%d",&n);
int i,j,tot=0;
for(i=1;i<=n;i++) {
scanf("%s",w+1);
l[i]=tot+1;
for(j=1;w[j];j++) s[++tot]=w[j]-'a';
r[i]=tot;
s[++tot]=26;
}
for(i=1;i<=tot;i++) insert(s[i]),siz[lst]++;
// printf("%d\n",flg[2]);
// print();
for(i=1;i<=cnt;i++) ws[dep[i]]++;
for(i=1;i<=cnt;i++) ws[i]+=ws[i-1];
for(i=1;i<=cnt;i++) a[ws[dep[i]]--]=i;
for(i=cnt;i;i--) {
int p=a[i];
siz[fa[p]]+=siz[p];
}
for(i=1;i<=n;i++) {
int p=1;
// printf("%d %d\n",l[i],r[i]);
for(j=l[i];j<=r[i];j++) p=ch[p][s[j]];
// printf("p=%d\n",p);
printf("%d\n",siz[p]);
}
}
BZOJ_3172_[Tjoi2013]单词_后缀自动机的更多相关文章
- 洛谷P3966 [TJOI2013]单词(后缀自动机)
传送门 统计单词出现次数……为啥大家都是写AC自动机的嘞……明明后缀自动机也能做的说…… 统计出现次数这个就直接按长度排序然后做个dp就好,这是SAM的板子的要求啊,不提了 然后考虑怎么让所有串之间隔 ...
- 【BZOJ】3172: [Tjoi2013]单词(后缀自动机)
http://www.lydsy.com/JudgeOnline/problem.php?id=3172 随便搞个sam就行了.(其实一开始看到数据n<=200, 单词长度不超过1e6,然后感觉 ...
- BZOJ_3172_[Tjoi2013]单词_AC自动机
BZOJ_3172_[Tjoi2013]单词_AC自动机 Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. ...
- BZOJ_3238_[Ahoi2013]差异_后缀自动机
BZOJ_3238_[Ahoi2013]差异_后缀自动机 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sam ...
- BZOJ_4199_[Noi2015]品酒大会_后缀自动机
BZOJ_4199_[Noi2015]品酒大会_后缀自动机 Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席 ...
- BZOJ_4566_[Haoi2016]找相同字符_后缀自动机
BZOJ_4566_[Haoi2016]找相同字符_后缀自动机 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有 ...
- BZOJ_3998_[TJOI2015]弦论_后缀自动机
BZOJ_3998_[TJOI2015]弦论_后缀自动机 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行 ...
- BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机+贪心
BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机 Description FJ刚刚和邻居发生了一场可怕的争吵,他咽不下这口气,决定佚名发给他的邻居 一封脏话连篇的信. ...
- BZOJ3172&&lg3966 TJOI单词(广义后缀自动机)
BZOJ3172&&lg3966 TJOI单词(广义后缀自动机) 题面 自己找去 HINT 给出多个文本串,让你查找每个文本串一共出现了多少次,广义后缀自动机建出parent tree ...
随机推荐
- BC#76.2DZY Loves Balls
DZY Loves Balls Accepts: 659 Submissions: 1393 Time Limit: 4000/2000 MS (Java/Others) Memory Lim ...
- Epic Moments
网络流序号要考虑超级源和超级汇 SAP要记得即使还原当前弧 二分图匹配中v.w要取局部变量 RMQ时记得开大数组 树链剖分记得结点要变为线段树中的下标
- 洛谷P3094 [USACO13DEC]假期计划Vacation Planning
题目描述 有N(1 <= N <= 200)个农场,用1..N编号.航空公司计划在农场间建立航线.对于任意一条航线,选择农场1..K中的农场作为枢纽(1 <= K <= 100 ...
- msp430入门编程30
msp430中C语言的文件管理
- PHP 基础复习 2018-06-21
(1)PHP Zip File 函数 $zip = zip_open("test.zip"); if ($zip) { while ($zip_entry = zip_read($ ...
- Codeforces 559A(计算几何)
A. Gerald's Hexagon time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- linux C 中的volatile使用
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了.精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存 ...
- Linux中断处理驱动程序编写
本章节我们一起来探讨一下Linux中的中断 中断与定时器:中断的概念:指CPU在执行过程中,出现某些突发事件急待处理,CPU暂停执行当前程序,转去处理突发事件,处理完后CPU又返回原程序被中断的位置继 ...
- 常见machine learning模型实现
一.感知机模型 二.线性回归(Linear Regression) from numpy import * def loadData(filename): x = [] y = [] f = open ...
- Rust 1.7.0 匹配器 match 的简介和使用
使用过正則表達式的人应该都知道 matcher ,通过 matcher 匹配器运算正則表達式,完毕一系列的匹配规则. 在Rust 中 没有 switch 语句.matcher 就是 switch 的一 ...