题目: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. Hibernate关联关系映射之一对一关联关系

    人和身份证之间就是一个典型的一对一关联关系.实现一对一关联关系映射的方式有两种一种是基于外键,一种是基于主键,下面我们先看基于外键的关联方式 首先看他们的实体类 Person类 ? 1 2 3 4 5 ...

  2. Spring积累

    <tx:annotation-driven/>  (Spring的XML配置里两大Bean的声明之一) 那我们是否就可以在程序中所有被spring管理的类(@Controller.@Ser ...

  3. Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum 树状数组+离线

    D. Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabytes in ...

  4. Springer Latex投稿

    大家好.我最近需要向springer旗下一期刊投稿,是用latex编写的.已经调试过,格式和出版的期刊比较接近.因为是第一次投国外期刊,所以没什么经验,在网上搜索了一些帖子,发现在投稿过程中还会出现这 ...

  5. ActiveMQ 性能调优

    本章重点 学习普通的性能调优技巧 怎么优化生产者和消费者 调优实例 简介 ActiveMQ 的性能高度依赖于多种不同的因素,包括:网络代理拓扑架构,传输层,底层网络的服务质量和速度,硬件,操作系统和 ...

  6. yii2:模块

    yii2:模块 模块不同于frontend/frontback单独的前后台单独的主题项目,模块不能单独部署,必须属于某个应用主体(如前后台:frontend/frontback). 模块置于modul ...

  7. lightoj1370欧拉函数/素数筛

    这题有两种解法,1是根据欧拉函数性质:素数的欧拉函数值=素数-1(可根据欧拉定义看出)欧拉函数定义:小于x且与x互质的数的个数 #include<map> #include<set& ...

  8. nt":false,"tarball":"http://registry.npm.taobao.org/babel-preset-stag

    npm ERR! Unexpected end of input at 1:12777 npm ERR! nt":false,"tarball":"http:/ ...

  9. ZOJ 3211 Dream City(线性DP)

    Dream City Time Limit: 1 Second      Memory Limit: 32768 KB JAVAMAN is visiting Dream City and he se ...

  10. LeetCode OJ:Best Time to Buy and Sell Stock II(股票买入卖出最佳实际II)

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...