Codeforces 666E Forensic Examination SAM+权值线段树
第一次做这种\(SAM\)带权值线段树合并的题 然而\(zjq\)神犇看完题一顿狂码就做出来了 \(Orz\)
首先把所有串当成一个串建\(SAM\) 我们对\(SAM\)上每个点 建一棵权值线段树 每个叶子节点表示一个匹配串能到达这个点的子串个数 这样我们对最后的\(SAM\)的权值线段树按\(parent\)树合并 询问的时候找到对应的\(SAM\)上的权值线段树直接查询就好了
具体的操作看代码吧~
#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi first
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
const int INF = 0x7fffffff;
const int N=1230010;
/*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
int x=0,rev=0,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return rev?-x:x;
}
pa operator * (const pa&A,const pa&B){return A.fi==B.fi?(A.se<B.se?A:B):(A.fi>B.fi?A:B);}
pa operator + (const pa&A,const pa&B){return mk(A.fi+B.fi,A.se);}
pa t[N*23];
char s[N];
int n,m,Q,c[N][27],par[N],len[N],fa[N][21],ls[N*23],rs[N*23],h[N],rt=1,sz=1,last=1,root[N],w[N],b[N],id;
void extend(int x){
int np=++sz,p=last;
len[np]=len[p]+1,last=np;
for(;p&&!c[p][x];p=par[p]) c[p][x]=np;
if(!p) par[np]=rt;
else{
int q=c[p][x];
if(len[p]+1==len[q]) par[np]=q;
else{
int nq=++sz;
len[nq]=len[p]+1,par[nq]=par[q],par[q]=par[np]=nq;
memcpy(c[nq],c[q],sizeof c[nq]);
for(;p&&c[p][x]==q;p=par[p]) c[p][x]=nq;
}
}
}
void modify(int&pos,int l,int r,int x){
if(!pos) pos=++id;
if(l==r){
t[pos].fi++,t[pos].se=l;
// cout<<t[pos].fi<<" "<<t[pos].se<<endl;
return;
}
int mid=l+r>>1;
if(x<=mid) modify(ls[pos],l,mid,x);
else modify(rs[pos],mid+1,r,x);
t[pos]=t[ls[pos]]*t[rs[pos]];
}
inline int merge(int x,int y,int l,int r)
{
if (!x||!y) return x|y;
int z=++id;
if (l==r) {
t[z]=t[x]+t[y];
return z;
}
int mid=(l+r)>>1;
ls[z]=merge(ls[x],ls[y],l,mid),rs[z]=merge(rs[x],rs[y],mid+1,r);
t[z]=t[ls[z]]*t[rs[z]];
return z;
}
pa Query(int pos,int l,int r,int nl,int nr){
if(!pos) return mk(0,0);
if(nl<=l&&r<=nr) return t[pos];
int mid=l+r>>1;
if(nr<=mid) return Query(ls[pos],l,mid,nl,nr);
else if(nl>mid) return Query(rs[pos],mid+1,r,nl,nr);
else return Query(ls[pos],l,mid,nl,nr)*Query(rs[pos],mid+1,r,nl,nr);
}
void topsort(){
for(int i=1;i<=sz;i++) w[len[i]]++;
for(int i=1;i<=sz;i++) w[i]+=w[i-1];
for(int i=1;i<=sz;i++) b[w[len[i]]--]=i;
for(int i=sz;i;i--){
int j=b[i];
if(par[j]) root[par[j]]=merge(root[par[j]],root[j],1,n);
}
}
void get_fa(){
for(int i=1;i<=sz;i++) fa[i][0]=par[i];
for(int i=1;i<=20;i++) for(int j=1;j<=sz;j++) fa[j][i]=fa[fa[j][i-1]][i-1];
}
int get(int l,int r){
int L=r-l+1,x=h[r];
for(int i=20;~i;i--) if(len[fa[x][i]]>=L) x=fa[x][i];
// -len[par[x]]-len[par[fa[x][i]]]
return x;
}
int main(){
#ifdef Devil_Gary
freopen("in.txt","r",stdin);
#endif
scanf("%s",s+1),m=strlen(s+1);
for(int i=1;i<=m;i++) extend(s[i]-'a'),h[i]=last;
n=read();
for(int i=1;i<=n;i++){
scanf("%s",s+1),m=strlen(s+1),extend(26);
for(int j=1;j<=m;j++) extend(s[j]-'a'),modify(root[last],1,n,i);
}
// bug(sz);
topsort(),get_fa();
for(Q=read();Q;Q--){
int l=read(),r=read(),pl=read(),pr=read(),x=get(pl,pr);
pa ans=Query(root[x],1,n,l,r);
if(!ans.fi) printf("%d 0\n",l);
else printf("%d %d\n",ans.se,ans.fi);
}
}
Codeforces 666E Forensic Examination SAM+权值线段树的更多相关文章
- Codeforces 666E Forensic Examination SAM or SA+线段树合并
E. Forensic Examination http://codeforces.com/problemset/problem/666/E 题目大意:给模式串S以及m个特殊串,q个询问,询问S的子串 ...
- Codeforces.666E.Forensic Examination(广义后缀自动机 线段树合并)
题目链接 \(Description\) 给定串\(S\)和\(m\)个串\(T_i\).\(Q\)次询问,每次询问\(l,r,p_l,p_r\),求\(S[p_l\sim p_r]\)在\(T_l\ ...
- CF666E Forensic Examination SAM+倍增,线段树和并
题面: 给你一个串S以及一个字符串数组T[1..m],q次询问,每次问S的子串S[p_l..p_r]在T[l..r]中的哪个串里的出现次数最多,并输出出现次数.如有多解输出最靠前的那一个. 分析: 第 ...
- CF 666E Forensic Examination——广义后缀自动机+线段树合并
题目:http://codeforces.com/contest/666/problem/E 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...
- Codeforces 558E A Simple Task(权值线段树)
题目链接 A Simple Task 题意 给出一个小写字母序列和若干操作.每个操作为对给定区间进行升序排序或降序排序. 考虑权值线段树. 建立26棵权值线段树.每次操作的时候先把26棵线段树上的 ...
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- D. Restore Permutation(权值线段树)
D. Restore Permutation time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)
layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
随机推荐
- ZSTU OJ 3770: 黑帽子 归纳总结
Description 一群非常聪明的人开舞会,每人头上都戴着一顶帽子.帽子只有黑白两种,黑的至少有一顶.每个人都能看到其它人帽子的颜色,却看不到自己的.主持人先让大家 看看别人头上戴的是什幺帽子,然 ...
- 前端 ajax 改写登录界面
SSM 整合项目开发到一个阶段,想慢慢地把前台框架等技术引入进来 突然碰到一个困惑好久的问题: ajax 替换原本 form 表单 post 提交登录: 一直 404 错误,心塞.... 最后发现原来 ...
- Request.Cookies 和 Response.Cookies 的区别
.NET中提供了读写Cookie的多种方法,Request.Cookies 是客户端通过 Cookie 标头形式由客户端传输到服务器的 Cookie:Response.Cookies 在服务器上创建并 ...
- ASP.NET真假分页—真分页
当数据量过大,有几万甚至十几万条数据时,每次都从数据库中取出所有数据就会降低查询效率,系统运行慢,还有可能卡死,这时假分页就会显得很不人性化,因此有了真分页的必要性. 正如上篇博文总结归纳,“真”相对 ...
- MAC Book 共享网络连接
CHENYILONG Blog MAC Book 共享网络连接 MAC Book 共享网络连接 MAC比Windows共享连接要方便很多,只需要以下两步操作: 1.打开系统偏好设置,选择共享 2.选择 ...
- c++刷题(30/100)
题目一:合并两个排序的链表 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 思路:利用两个指针cur1,cur2来指分别向两个链表中当前较小的和当前较大的 ...
- Spark笔记之使用UDF(User Define Function)
一.UDF介绍 UDF(User Define Function),即用户自定义函数,Spark的官方文档中没有对UDF做过多介绍,猜想可能是认为比较简单吧. 几乎所有sql数据库的实现都为用户提供了 ...
- 【ORACLE】oracl基本操作笔记
1.用命令导入导出表 C:\Users\xiang>imp bjlims/bjlims@orcl file="c:\tjlims.dmp" full=y C:\Users\x ...
- C++(vs)多线程调试 (转)
在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”.利用线程,用户可按下一个按钮,然后程序会立即作出响应,而不是让用户等待程序完成了当前任务以后 ...
- 【ARTS】01_08_左耳听风-20181231~20190106
ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...