题目: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 树一样处理了重复节点;

基数排序后DP,f 数组求的直接是这个点及其祖先的答案;

开 2e5 就可以,因为每次加入一个字符最多新增2个点。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=2e5+;
int n,K,cnt=,go[xn][],len[xn],fa[xn],vis[xn],tot[xn],lst;
ll f[xn];
string s[xn];
int work(int p,int w)
{
int nq=++cnt,q=go[p][w]; len[nq]=len[p]+;
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q]; fa[q]=nq;
for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
return nq;
}
int ext(int p,int w)
{
if(go[p][w])
{
int q=go[p][w];
if(len[q]==len[p]+)return q; return work(p,w);
}
int np=++cnt; len[np]=len[p]+;
for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
if(!p)fa[np]=;
else
{
int q=go[p][w];
if(len[q]==len[p]+)fa[np]=q;
else fa[np]=work(p,w);
}
return np;
}
int tax[xn],q[xn],l[xn];
void rsort()
{
for(int i=;i<=cnt;i++)tax[len[i]]++;
for(int i=;i<=cnt;i++)tax[i]+=tax[i-];
for(int i=cnt;i;i--)q[tax[len[i]]--]=i;
}
char dc[xn];
int main()
{
scanf("%d%d",&n,&K);
for(int i=;i<=n;i++)
{
scanf("%s",dc); s[i]=string(dc); l[i]=strlen(dc); lst=;
for(int j=;j<l[i];j++)lst=ext(lst,s[i][j]-'a');
}
for(int i=;i<=n;i++)
{
int nw=;
for(int j=;j<l[i];j++)
{
nw=go[nw][s[i][j]-'a'];
for(int p=nw;p&&vis[p]!=i;p=fa[p])vis[p]=i,tot[p]++;
}
}
rsort();
for(int i=,x;i<=cnt;i++)
f[x=q[i]]=f[fa[x]]+(tot[x]>=K?len[x]-len[fa[x]]:);//
for(int i=;i<=n;i++)
{
ll ans=; int nw=;
for(int j=;j<l[i];j++)
nw=go[nw][s[i][j]-'a'],ans+=f[nw];
printf("%lld ",ans);
}
puts(""); return ;
}

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2780

几乎完全一样,但忘记写 lst=1 呆了半小时...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=2e5+;
int n,m,cnt=,fa[xn],l[xn],go[xn][],len[xn],tot[xn],vis[xn],lst;
char dc[xn]; string s[xn];
int work(int p,int w)
{
int nq=++cnt,q=go[p][w]; len[nq]=len[p]+;
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q]; fa[q]=nq;
for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
return nq;
}
int ext(int p,int w)
{
if(go[p][w])
{
int q=go[p][w];
if(len[q]==len[p]+)return q; return work(p,w);
}
int np=++cnt; len[np]=len[p]+;
for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
if(!p)fa[np]=;
else
{
int q=go[p][w];
if(len[q]==len[p]+)fa[np]=q;
else fa[np]=work(p,w);
}
return np;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",dc); l[i]=strlen(dc); s[i]=string(dc); lst=;//lst=1!!
for(int j=;j<l[i];j++)lst=ext(lst,s[i][j]-'a');
}
for(int i=;i<=n;i++)
{
int nw=;
for(int j=;j<l[i];j++)
{
nw=go[nw][s[i][j]-'a'];
for(int p=nw;p&&vis[p]!=i;p=fa[p])vis[p]=i,tot[p]++;
}
}
for(int i=;i<=m;i++)
{
scanf("%s",dc); int lth=strlen(dc),nw=;
for(int j=;j<lth;j++)nw=go[nw][dc[j]-'a'];
printf("%d\n",tot[nw]);
}
return ;
}

bzoj 3277 & bzoj 3473,bzoj 2780 —— 广义后缀自动机的更多相关文章

  1. BZOJ 3473: 字符串 (广义后缀自动机)

    /* 广义后缀自动机, 每次加入维护 该right集合的set, 然后可以更新所有的parent,最终能够出现在k个串中right集合也就是set大小大于等于k的部分 这样的话就给了我们要跳的节点加了 ...

  2. BZOJ 4566 [Haoi2016]找相同字符 ——广义后缀自动机

    建立广义后缀自动机. 然后统计子树中的siz,需要分开统计 然后对(l[i]-l[fa[i]])*siz[i][0]*siz[i][1]求和即可. #include <cstdio> #i ...

  3. BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2806 (luogu) https://www.luogu.org/pro ...

  4. bzoj 4566 [Haoi2016]找相同字符——广义后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4566 每个后缀结尾处 ct[ ] = 1 ,按拓扑序 dp 一下就能求出 right 集合的 ...

  5. 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.p ...

  6. BZOJ 3277/3473 广义后缀自动机

    说实话没啥难的. 建一棵广义后缀自动机,暴力自底向上更新即可. 时间复杂度非常玄学,但据说是可以过的. 要注意每个串中相同的子串的贡献是都要加进去的,开始因为这个被坑了好久 QAQ Code: #in ...

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

    3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...

  8. BZOJ 3473: 字符串 [广义后缀自动机]

    3473: 字符串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 354  Solved: 160[Submit][Status][Discuss] ...

  9. BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(广义后缀自动机)

    题目链接 \(Description\) 给定n个模式串,多次询问一个串在多少个模式串中出现过.(字符集为26个小写字母) \(Solution\) 对每个询问串进行匹配最终会达到一个节点,我们需要得 ...

随机推荐

  1. [POI2012] BEZ-Minimalist Security

    一张n个点m条边的无向图,有点权有边权都是非负,且每条边的权值小于等于两个顶点的权值和,现在要将每个点减一个非负整数使得每条边权等于两个顶点的点权和,问最大修改代价和最小修改代价 思路神的一匹,完全想 ...

  2. JAVA基础补漏--反射

    获得CLASS的三种方式: 1.Class.forname("全类名"):将字节码文件加载进内存,返回Class对象. 多用于配置文件,将类名放到配置文件中,读取配置文件,加载类 ...

  3. Redis单线程原理

    redis是以socket方式通信,socket服务端可同时接受多个客户端请求连接,也就是说,redis服务同时面对多个redis客户端连接请求,而redis服务本身是单线程运行. 假设,现在有A,B ...

  4. Vue-深入-1

    1.关于vue get setVue 不能检测到对象属性的添加或删除 把一个普通 Javascript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object. ...

  5. 如何查看eclipse、mysql的版本 - 原创

    Eclipse 1)如果实在官网下载的,看压缩包名字就可以看出来,只带有win32字样的是32位,带有win32-x86_64字样的是64位的. 2)找到eclipse安装目录的eclipse.ini ...

  6. Java EE启示录

    前言 最近的这段时间一直在学习Java EE,刚刚完成了从0到1的蜕变,所以顺便整理一下我所了解到的Java EE,给刚入门学习的新人一些头绪,而所谓“启示录”,就是这个意思. 一.Java EE是什 ...

  7. Maven到底是个啥玩意

    Maven,是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. 上面是百度百科对Maven的正式介绍,如果你是Maven初学者,我估计你看完之后心中肯 ...

  8. LeetCode第[22]题(Java):Generate Parentheses

    题目:制造括号序列 难度:Medium 题目内容: Given n pairs of parentheses, write a function to generate all combination ...

  9. CodeForces - 767C

    花了6个小时,终于成功ac...... 两边dfs,第一遍求子树和,第二遍判断有没有2*t[s]/3和t[s]/3,因为要求的节点可能是在同一条线上,同时要有2*t[s]/3和t[s]/3的情况,且2 ...

  10. win8 商店应用 概观

    外观: 1,适应性好.可以在各种外形规格和显示大小上正确的展示数据. 2,磁贴. 交互方式: 1,应用栏.使用应用栏可以向用户显示命令和工具.默认情况下,应用栏会被隐藏,当用户使用手指从屏幕的底部边缘 ...