hdu 5853 Jong Hyok and String(广义后缀自动机)

题目链接:hdu 5853 Jong Hyok and String

题意:

给你n个字符串,m个询问,每次询问一个字符串

定义set(s)={(i,j)} 表示 s在第i个字符串中出现,且末尾位置为j。

对于一个询问,求set(Qi)=set(t) ,t串的数量。

题解:

如果是n=1,那么就是后缀自动机的一道裸题,答案就是Qi串匹配的最后一个节点x,ml[x]-ml[f[x]]。

现在是多个串,那么就建立一个广义后缀自动机。每次插入一个串后,将last=root,然后继续插下一个就行了。

最后匹配还是一样的操作。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define F(i,a,b) for(int i=a;i<=b;++i)
 4 #define mst(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6
 7 const int N=1e5+7,tyn=26,M=N*2;
 8 struct SAM{
 9     int tr[M][tyn],f[M],ml[M],ed,last,p,x,r,q;
10     int cnt[M],b[M],d[M];
11     inline int gid(char x){return x-‘a‘;}
12     inline void nc(int s,int &p){
13         ml[p=++ed]=s,f[ed]=cnt[ed]=0,mst(tr[ed],0);
14     }
15     void clear(){ed=0,nc(0,last);}
16     void add(int w){
17         nc(ml[x=last]+1,p),last=p,cnt[p]=1;
18         while(x&&!tr[x][w])tr[x][w]=p,x=f[x];
19         if(!x)f[p]=1;
20         else if(ml[x]+1==ml[q=tr[x][w]])f[p]=q;
21         else{
22             nc(ml[x]+1,r),f[r]=f[q],f[p]=f[q]=r;
23             memcpy(tr[r],tr[q],sizeof(tr[r]));
24             while(x&&tr[x][w]==q)tr[x][w]=r,x=f[x];
25         }
26     }
27     void build(char *s){for(int i=1;s[i];i++)add(gid(s[i]));}
28
29     int go(char *s,int x=1)//与s做匹配
30     {
31         int len=strlen(s+1);
32         for(int i=1;i<=len;i++)
33         {
34             int w=gid(s[i]);
35             if(tr[x][w])x=tr[x][w];
36             else return 0;
37         }
38         return ml[x]-ml[f[x]];
39     }
40 }sam;
41
42 char s[N];
43 int t,n,m,cas;
44
45 int main()
46 {
47     scanf("%d",&t);
48     while(t--)
49     {
50         scanf("%d%d",&n,&m);
51         sam.clear();
52         F(i,1,n)
53         {
54             sam.last=1;
55             scanf("%s",s+1);
56             sam.build(s);
57         }
58         printf("Case #%d:\n",++cas);
59         F(i,1,m)
60         {
61             scanf("%s",s+1);
62             printf("%d\n",sam.go(s));
63         }
64     }
65     return 0;
66 }

时间: 2024-10-31 11:47:26

hdu 5853 Jong Hyok and String(广义后缀自动机)的相关文章

hdu 5008 Boring String Problem(后缀自动机构造后缀树)

hdu 5008 Boring String Problem(后缀自动机构造后缀树) 题意:给出一个字符串s,然后每次询问一个k,求s的所有子串中,字典序第k小的是谁?多个解,则输出最左边的那个 解题思路:这道题应该是为后缀树量身定制的吧.只要构造出了后缀树,然后按字典序遍历就可以得出每个节点包含的子串的字典序的范围了,而且必然是个连续的区间范围.但是我不会后缀树啊..比赛的时候突然想到,后缀自动机是可以构造后缀树的,虽然以前没写过,但还是硬着头皮上吧,居然还真的让我给撸出来了.我的做法是这样的

BZOJ 3277 串 (广义后缀自动机)

3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 输出一行n个整数,第i个整数表示第i个字符串的答案. Sa

hdu 6599 I Love Palindrome String 回文自动机

hdu 6599 I Love Palindrome String 回文自动机 当个回文自动机的模板 题意 给一个串S,求长度为i的"特殊回文串"个数,"特殊回文串"要求是回文串,并且自己的一半也是回文串. 思路 求回文串个数相关,优先考虑使用回文自动机,"特殊回文串"要求是回文串,并且自己的一半也是回文串,显然就是fail树扒出来dfs搞一下,记录dfs路径上有没有长度一半的回文串即可. PS:因为fail指针的意义是最长后缀回文,反过来路径显

【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机

[BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来.也就是说,这n块空地形成了一个树的结构. 有n个粉丝们来到了太阳花田上.为了表达对幽香生日的祝

E. Three strings 广义后缀自动机

http://codeforces.com/problemset/problem/452/E 多个主串的模型. 建立一个广义后缀自动机,可以dp出每个状态的endpos集合大小.同时也维护一个R[]表示那个串出现过. 所以可以算出每个状态的dp[i][k]表示第k个串在第i个状态中出现的次数. 可以知道sigma dp[i][0...k]是等于  endpos集合的大小. 然后把这个贡献加到min(i)....max(i)中去就可以了 差分一下. #include <bits/stdc++.h>

广义后缀自动机

1).自动机的介绍 首先我们先来介绍一下什么是自动机,有限状态自动机的功能是识别字符串,令一个自动机A,若他能识别字符串S,就记为A(S)=Ture,否则A(S)=False. 自动机由五个部分组成,alpha:字符集,state:状态集合,init:初始状态,end:结束状态集合,trans:状态转移函数. 令trans(s,ch)表示当前状态是s,在读入字符ch之后,所到达的状态.如果trans(s,ch)这个转移不存在,为了方便,设其为null,同时null只能转移到null.null表示

【BZOJ2806】【CTSC2012】Cheat 广义后缀自动机+二分+Dp

题目 题目在这里 思路&做法 我们先对标准作文库建广义后缀自动机. 然后对于每一篇阿米巴的作文, 我们首先把放到广义后缀自动机跑一遍, 对于每一个位置, 记录公共子串的长度\((\)即代码和下文中的\(val\)数组\()\) 接着我们二分答案, 用DP检验. Dp方程很好想, \(d_i = max \{ d_j + i - j \ | \ i-val_i <= j <= i-lim \}\) 可以用单点队列优化. 代码 #include <iostream> #incl

【codeforces666E】Forensic Examination 广义后缀自动机+树上倍增+线段树合并

题目描述 给出 $S$ 串和 $m$ 个 $T_i$ 串,$q$ 次询问,每次询问给出 $l$ .$r$ .$x$ .$y$ ,求 $S_{x...y}$ 在 $T_l,T_{l+1},...,T_r$ 中的哪一个里出现次数最多,输出出现次数最多的串编号(如果有多个则输出编号最小的)以及相应出现次数. $|S|,q\le 5\times 10^5$ ,$\sum\limits_{i=1}^m|T_i|\le 5\times 10^4$ . 题解 广义后缀自动机+树上倍增+线段树合并 对 $S$

BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串

https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比较方便). 后缀自动机可以说是一种存子串的缩小点数的trie树,广义后缀自动机就是更改了一下塞点的方式让它可以塞多个子串. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<