bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277
https://www.lydsy.com/JudgeOnline/problem.php?id=3473
学习的博客:https://www.cnblogs.com/HocRiser/p/9580478.html
广义后缀自动机有两种写法,这里写的是 trie 树的那种。
大意就是每个串从自动机的根开始走,
1.如果存在 q = go[p][w] ,且 l [q] == l [p]+1 , 那么直接把 q 看作这次插入了的点,下次令 p = q ,续着往后插入;
2.如果存在 q = go[p][w] ,且 l [q] != l [p]+1 , 那么分出一个 nq 来,把 nq 看作这次插入了的点,下次令 p = nq ,续着往后插入;
3.如果不存在 q = go[p][w] ,就新建一个 np ;然后就是一个串的后缀自动机插入了;下次令 p = np 。
要计算后缀自动机上的每个点代表的那些子串在所有串里出现了多少次,记为 ct[ ] ;
在做一个串的插入的时候,考虑让一些位置的 ct[ ] ++ ;每插入一个字符,就跳 fa ,给所有 fa 的 ct[ ] ++ ;但如果已经被当前字符串的之前字符弄得 ct[ ] 加一过了,就不用再加了;
不要边建自动机边做 ct[ ] ++ ;因为那时的 parent 树还不是所有串的。
然后拓扑排序一下,从根到叶子做 dp ,自己节点可以贡献的合法子串个数 ans[ ] 就是 ans[ fa ] 再加上 “ 自己出现了 >= k 次?l [cr] - l [fa] : 0 ” 。
两道题用同样的代码即可。
#include<cstdio>
#include<cstring>
#include<string>//
#include<algorithm>
#define ll long long
using namespace std;
int Mx(int a,int b){return a>b?a:b;}
const int N=1e5+,M=N<<,K=;//<<1
int n,k,go[M][K],l[M],fa[M],tot=;
int tx[M],q[M],ans[M],ct[M],vis[M];
int cz(int p,int w)
{
int q=go[p][w],nq=++tot;l[nq]=l[p]+;
fa[nq]=fa[q];fa[q]=nq;
memcpy(go[nq],go[q],sizeof go[q]);
for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
return nq;
}
int ins(int p,int w)
{
if(go[p][w])
{
int q=go[p][w];
if(l[q]==l[p]+)return go[p][w];
else return cz(p,w);//////
}
else
{
int np=++tot;l[np]=l[p]+;
for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
if(!p)fa[np]=;
else
{
int q=go[p][w];
if(l[q]==l[p]+)fa[np]=q;
else fa[np]=cz(p,w);
}
return np;
}
}
void Rsort(int mxn)
{
for(int i=;i<=tot;i++)tx[l[i]]++;
for(int i=;i<=mxn;i++)tx[i]+=tx[i-];
// for(int i=tot;i;i--)q[tx[l[i]]--]=i;
for(int i=;i<=tot;i++)q[tx[l[i]]--]=i;
}
string ch[N]; int len[N];
int main()
{
scanf("%d%d",&n,&k); char tp[N]; int mxn=;
for(int i=,d;i<=n;i++)
{
scanf("%s",tp);len[i]=strlen(tp);mxn=Mx(mxn,len[i]);
ch[i]=tp;
}
for(int i=;i<=n;i++)
for(int lm=len[i],pr=,j=;j<lm;j++)
pr=ins(pr,ch[i][j]-'a'+);
for(int i=;i<=n;i++)
for(int lm=len[i],cr=,j=;j<lm;j++)
{
cr=go[cr][ch[i][j]-'a'+];
for(int p=cr;p&&vis[p]!=i;p=fa[p])
ct[p]++,vis[p]=i;
}
Rsort(mxn);
for(int i=,d;i<=tot;i++)
{d=q[i];ans[d]=ans[fa[d]]+(ct[d]>=k?l[d]-l[fa[d]]:);}//
for(int i=;i<=n;i++)
{
ll prn=;
for(int lm=len[i],cr=,j=;j<lm;j++)
{
cr=go[cr][ch[i][j]-'a'+];
prn+=ans[cr];
}
printf("%lld ",prn);
}
puts("");return ;
}
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2780
和上一道题一样。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
int const xn=2e5+;
const int N=1e4+,M=2e5+,N2=4e5+,K=;
int n,go[M][K],fa[M],l[M],ct[M],tot=;
string s[N];int len[N],vis[M];
int cz(int p,int w)
{
int q=go[p][w],nq=++tot; l[nq]=l[p]+;/////////l[p]+1 not l[q]+1!!!!!
fa[nq]=fa[q];fa[q]=nq;
memcpy(go[nq],go[q],sizeof go[q]);
for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
return nq;
}
int ins(int p,int w)
{
if(go[p][w])
{
int q=go[p][w];
if(l[q]==l[p]+)return q; else return cz(p,w);
}
else
{
int np=++tot;l[np]=l[p]+;
for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
if(!p)fa[np]=;
else
{
int q=go[p][w];
if(l[q]==l[p]+)fa[np]=q; else fa[np]=cz(p,w);
}
return np;
}
}
char ch[N2]; int Q;
int main()
{
scanf("%d%d",&n,&Q);
for(int i=;i<=n;i++)
{
scanf("%s",ch);len[i]=strlen(ch);
s[i]=(string)ch;
for(int pr=,j=,lm=len[i];j<lm;j++)
pr=ins(pr,ch[j]-'a'+);
}
for(int i=;i<=n;i++)
for(int cr=,j=,lm=len[i];j<lm;j++)
{
cr=go[cr][s[i][j]-'a'+];
for(int p=cr;p>&&vis[p]!=i;p=fa[p])
ct[p]++,vis[p]=i;
}
while(Q--)
{
scanf("%s",ch);int lm=strlen(ch),cr=;
for(int j=;j<lm&&cr;j++)
cr=go[cr][ch[j]-'a'+];
printf("%d\n",ct[cr]);
}
return ;
}
bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机的更多相关文章
- BZOJ 2780 [Spoj]8093 Sevenk Love Oimaster ——广义后缀自动机
给定n个串m个询问,问每个串在n个串多少个串中出现了. 构建广义后缀自动机,(就是把所有字符串的后缀自动机合并起来)其实只需要add的时候注意一下就可以了. 然后对于每一个串,跑一边匹配,到达了now ...
- BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster [广义后缀自动机]
JZPGYZ - Sevenk Love Oimaster Oimaster and sevenk love each other. But recently,sevenk hea ...
- 三种做法:BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster
目录 题意 思路 AC_Code1 AC_Code2 AC_Code3 参考 @(bzoj 2780: [Spoj]8093 Sevenk Love Oimaster) 题意 链接:here 有\(n ...
- BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )
全部串起来做SA, 在按字典序排序的后缀中, 包含每个询问串必定是1段连续的区间, 对每个询问串s二分+RMQ求出包含s的区间. 然后就是求区间的不同的数的个数(经典问题), sort queries ...
- BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(广义后缀自动机)
题目链接 \(Description\) 给定n个模式串,多次询问一个串在多少个模式串中出现过.(字符集为26个小写字母) \(Solution\) 对每个询问串进行匹配最终会达到一个节点,我们需要得 ...
- bzoj 2780 [Spoj]8093 Sevenk Love Oimaster
LINK:Sevenk Love Oimaster 询问一个模式串在多少个文本串中出现过. 考虑广义SAM 统计这种数量问题一般有三种做法. 一种 暴力bitset 这道题可能可以过? 一种 暴力跳p ...
- 【刷题】BZOJ 2780 [Spoj]8093 Sevenk Love Oimaster
Description Oimaster and sevenk love each other. But recently,sevenk heard that a girl named ChuYuXu ...
- bzoj 2780: [Spoj]8093 Sevenk Love Oimaster(广义SAM)
题目大意:给出n个原串,再给出m个查询串.求每个查询串出现在了多少原串中. 题解 直接对原串建一个广义SAM,然后把每一个原串放到SAM上跑一跑,记录一下每一个状态属于多少个原串,用$size$表示. ...
- bzoj 2780: [Spoj]8093 Sevenk Love Oimaster【广义SAM】
AC自动机比较简单,把询问串做成AC自动机然后模板串边跑变更新即可 SAM是把模板串做成广义SAM,然后每个节点存有几个模板串经过,具体方法是每次更新暴力向上跳直到有时间戳我不会证为什么时间复杂度是对 ...
随机推荐
- http 请求和格式
get 请求:从指定的资源请求数据. post请求:向指定的资源提交要被处理的数据. head请求:与 GET 相同,但只返回 HTTP 报头,不返回资源实体. option请求:返回服务器支持的 H ...
- Is your JDeveloper Slow? - It shouldn't be!(转)
我的Jdeveloper随便点一个AM,code的显示速度和手指的反应速度跟不上,真的是着急,忍了好久,找到以下教程. 经过考虑,仅仅只是在jdev.conf(jdevbin/jdev/bin/jde ...
- httpclient http状态管理
HTTP状态管理 最初,Htt被设计成一个无状态的面向请求响应的协议,所以它不能再逻辑相关的http请求/响应中保持状态会话. 由于越来越多的系统使用http协议,其中包括http从来没有想支持的系统 ...
- weblogic下更改jsp不生效的解决办法
1.删除user_projects\domains\base_domain(我自己的域名)\servers\AdminServer目录下的所有文件夹 一下为转载from:http://blog.itp ...
- Struts2的手工自定义验证--完整实例代码
ActionSupport类实现了Validateable.ValidationAware接口, 其中Validateable接口就是验证器接口,该接口有一个validate()方法, validat ...
- 玩转X-CTR100 l STM32F4 l 红外遥控接收
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] X-CTR100控制器具有红外接收头,例程 ...
- MyEclipse WebSphere开发教程:安装和更新WebSphere 6.1, JAX-WS, EJB 3.0(三)
MyEclipse超值折扣 限量 100 套! 立即开抢>> [MyEclipse最新版下载] MyEclipse支持Java EE技术(如JAX-WS和EJB 3.0),它们以功能包的形 ...
- html内容滚动
<marquee srolldelay="50" direction="up"></marquee> 滚动标签<marquee&g ...
- [转载]三款SDR平台对比:HackRF,bladeRF和USRP
这篇文章是 Taylor Killian 13年8月发表在自己的博客上的.他对比了三款平价的SDR平台,认为这三款产品将是未来一年中最受欢迎的SDR平台.我觉得这篇文章很有参考价值,简单翻译一份转过来 ...
- makefile的一个错误:*** missing separator
原文转自:http://blog.sina.com.cn/s/blog_87c063060101c9yp.html 1.在写 多目录下makefile的时候,碰到一个错误提示,让我纠结许久,后面还是解 ...