Spoj8093 Sevenk Love Oimaster
题解:
对于所有n串建广义后缀自动机。
(广义后缀自动机唯一区别就是每次将las附成1,并不需要在插入时特判)
建完后再建出parent树,然后用dfs序+树状数组搞区间不同种类。
其实就是HH的项链+广义后缀自动机。很水的。(虽然我调了半个晚上)
代码:
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
int n,q;
char s[];
int ic(char c)
{
if(c>='a'&&c<='z')return c-'a'+;
if(c>='A'&&c<='Z')return c-'A'+;
if(c>=''&&c<='')return c-''+;
if(c==',')return ;
if(c=='.')return ;
return ;
}
int tin[*N],tout[*N],tim,pla[*N];
struct SAM
{
struct node
{
int len,pre,trs[];
vector<int>v;
}p[*N];
int tot,las;
SAM(){tot=las=;}
void res(){las=;}
void insert(int c,int k)
{
int np,nq,lp,lq;
np = ++tot;
p[np].len = p[las].len+;
for(lp=las;lp&&!p[lp].trs[c];lp=p[lp].pre)
p[lp].trs[c]=np;
if(!lp)p[np].pre = ;
else
{
lq = p[lp].trs[c];
if(p[lq].len == p[lp].len+)p[np].pre = lq;
else
{
nq = ++tot;
p[nq] = p[lq];
p[nq].len = p[lp].len+;
p[lq].pre = p[np].pre = nq;
while(p[lp].trs[c]==lq)
{
p[lp].trs[c]=nq;
lp=p[lp].pre;
}
}
}
las = np;
p[las].v.push_back(k);
}
int hed[*N],cnt;
struct EG
{
int to,nxt;
}e[*N];
void ae(int f,int t)
{
e[++cnt].to = t;
e[cnt].nxt = hed[f];
hed[f] = cnt;
}
void dfs(int u)
{
tin[u]=++tim;pla[tim]=u;
for(int j=hed[u];j;j=e[j].nxt)dfs(e[j].to);
tout[u]=tim;
}
void build()
{
for(int i=;i<=tot;i++)
ae(p[i].pre,i);
dfs();
}
}sam;
int ans[],ct;
struct Pair
{
int l,r,id;
}qu[];
bool cmp(Pair a,Pair b)
{
return a.r<b.r;
}
int f[*N];
void up(int x,int d)
{
if(!x)return ;
while(x<=)f[x]+=d,x+=(x&(-x));
}
int down(int x)
{
if(!x)return ;
int ret = ;
while(x)ret+=f[x],x-=(x&(-x));
return ret;
}
int las[];
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)
{
scanf("%s",s+);
int len = strlen(s+);
sam.res();
for(int j=;j<=len;j++)
sam.insert(ic(s[j]),i);
}
sam.build();
for(int i=;i<=q;i++)
{
scanf("%s",s+);
int len = strlen(s+);
int u = ;
for(int j=;j<=len&&u;j++)
u=sam.p[u].trs[ic(s[j])];
if(u)
{
ct++;
qu[ct].l = tin[u];
qu[ct].r = tout[u];
qu[ct].id = i;
}
}
sort(qu+,qu++ct,cmp);
for(int k=,i=;i<=tim;i++)
{
for(int j=;j<sam.p[pla[i]].v.size();j++)
{
up(i,);
up(las[sam.p[pla[i]].v[j]],-);
las[sam.p[pla[i]].v[j]]=i;
}
int tmp = down(i);
for(;qu[k].r==i;k++)
ans[qu[k].id] = tmp - down(qu[k].l-);
}
for(int i=;i<=q;i++)
printf("%d\n",ans[i]);
return ;
}
Spoj8093 Sevenk Love Oimaster的更多相关文章
- BZOJ2780:[SPOJ8093]Sevenk Love Oimaster(广义SAM)
Description Oimaster and sevenk love each other. But recently,sevenk heard that a girl named ChuYuXu ...
- BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(广义后缀自动机)
题目链接 \(Description\) 给定n个模式串,多次询问一个串在多少个模式串中出现过.(字符集为26个小写字母) \(Solution\) 对每个询问串进行匹配最终会达到一个节点,我们需要得 ...
- [BZOJ2780][SPOJ8093]Sevenk Love Oimaster
bzoj luogu 题面 给定n个模板串,以及m个查询串. 依次查询每一个查询串是多少个模板串的子串. sol 广义后缀自动机裸题? 先建出\(SAM\),然后记录一下每个节点分别在多少个模板串里出 ...
- [bzoj2780][Spoj8093]Sevenk Love Oimaster_广义后缀自动机
Sevenk Love Oimaster bzoj-2780 Spoj-8093 题目大意:给定$n$个大串和$m$次询问,每次给出一个字符串$s$询问在多少个大串中出现过. 注释:$1\le n\l ...
- BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )
全部串起来做SA, 在按字典序排序的后缀中, 包含每个询问串必定是1段连续的区间, 对每个询问串s二分+RMQ求出包含s的区间. 然后就是求区间的不同的数的个数(经典问题), sort queries ...
- BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster [广义后缀自动机]
JZPGYZ - Sevenk Love Oimaster Oimaster and sevenk love each other. But recently,sevenk hea ...
- SP8093 JZPGYZ - Sevenk Love Oimaster 解题报告
SP8093 JZPGYZ - Sevenk Love Oimaster 题目大意 给定\(n(n\le 10000)\)个模板串,以及\(m(m\le 60000)\)个查询串(模板串总长\(\le ...
- 【BZOJ2780】【SPOJ】Sevenk Love Oimaster(后缀自动机)
[BZOJ2780][SPOJ]Sevenk Love Oimaster(后缀自动机) 题面 BZOJ 洛谷 题解 裸的广义后缀自动机??? 建立广义后缀自动机建立出来之后算一下每个节点被几个串给包括 ...
- 【BZOJ2780】[Spoj]8093 Sevenk Love Oimaster 广义后缀自动机
[BZOJ2780][Spoj]8093 Sevenk Love Oimaster Description Oimaster and sevenk love each other. But r ...
随机推荐
- 洛谷 - P2805 - 植物大战僵尸 - 最大流 - 最大权闭合子图
https://www.luogu.org/problemnew/show/P2805 最大权闭合子图的特点是,假如你要选一个结点,则要先选中它的所有子节点.正权连S负权连T,容量为绝对值,原图有向边 ...
- 洛谷 - P1739 - 表达式括号匹配 - 模拟 - 栈
https://www.luogu.org/problemnew/show/P1739 虽然应该是用栈的……但是直接模拟就可以了. #include<bits/stdc++.h> usin ...
- (水题)洛谷 - P1583 - 魔法照片
https://www.luogu.org/problemnew/show/P1583 设计一个strcut cmp用来比较,就可以了. #include<bits/stdc++.h> u ...
- hdu 3622 Bomb Game【二分+2-SAT+tarjan】
用read()会挂 二分半径,显然最优的是所有原都用这个最小半径,然后2-SAT把相交的圆建图,跑tarjan判一下可行性即可 #include<iostream> #include< ...
- 浅谈单调栈 By cellur925
这位dalao的单调栈文章很棒!我写的是他的题单233. http://www.cnblogs.com/COLIN-LIGHTNING/p/8474668.html 一.单调栈的一般写法 ;i< ...
- 力荐!35 个最好用的 Vue 开源库!
无论是开发新手还是经验丰富的老手,我们都喜欢开源软件包.对于开发者来说,如果没有这些开源软件包,很难想象我们的生活会变得多么疲惫不堪,而且靠咖啡度日也会成为家常便饭.所幸的是,随着 Vue.js 和 ...
- Centos6.8 搭建 Mysql 主从复制
实例环境: MySQL-Master:Centos-6.8:192.168.153.130 MySQL-Slave:Centos-6.8:192.168.153.131 1.两台服务器安装mysql ...
- Codeforces Round #319 (Div. 2)
水 A - Multiplication Table 不要想复杂,第一题就是纯暴力 代码: #include <cstdio> #include <algorithm> #in ...
- scau 17967 大师姐唱K的固有结界 分类暴力 + RMQ
由于能放两次,那么分类, 1.连续使用,(这个直接O(n^2)暴力) 2.分开使用. 分开使用的话,首先暴力枚举,用T时间,能从第1个位置,唱到第几首歌,然后剩下的就是从pos + 1, n这个位置, ...
- android开发学习 ------- 枚举类型在Android中的用法
一般上为了简化代码,重用代码,设置标志位来表示不同的流程,这个标志位可以使用枚举类型来表示: 1:定义 public FbManner fbManer = FbManner.EMAIL; //给一个默 ...