【BZOJ3413】匹配 离线+后缀树+树状数组
【BZOJ3413】匹配
Description
Input
第一行包含一个整数n(≤100000)。
第二行是长度为n的由0到9组成的字符串。
第三行是一个整数m。
接下来m≤5·10行,第i行是一个由0到9组成的字符串s,保证单行字符串长度小于等于10^5,所有字符串长度和小于等于3·10^6
Output
输出m行,第i行表示第si和S匹配所比较的次数。
Sample Input
1090901
4
87650
0901
109
090
Sample Output
10
3
4
题解:题目是问你截止到匹配之前,A串的每个位置与B串的LCP+1之和。这要利用到一个性质,两个后缀的lcp长度等于后缀树上两个点的lca的mx值。所以我们对A串的反串建立后缀自动机,得到后缀树,然后将B串放到后缀树中进行匹配(后缀树中匹配不同于后缀自动机中的匹配,实现比较复杂,方法也有很多,可以看代码)。如果没有成功匹配,则我们取最后一个成功匹配的节点,从这个点沿着到根的路径一路走上去跑一个树形DP即可。如果匹配成功,我们记录一下匹配成功的节点以及匹配位置,然后离线处理。我们将原串中的点一个一个加到后缀树中去,用树状数组维护DFS序得到子树和,处理询问时依旧跑类似于树形DP的东西即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N=200010; int n,m,tot,last,cnt;
char S[N],T[N];
int ch[N][10],mx[N],pre[N],p1[N],p2[N],mn[N],pos[N],qos[N],len[N],s[N],L[N],R[N],son[N][10],siz[N];
vector<int> q[N];
vector<int>::iterator it;
int f[N];
ll ans[N];
inline int extend(int x)
{
int p=last,np=++tot; last=np;
mx[np]=mx[p]+1,siz[np]=1;
for(;p&&!ch[p][x];p=pre[p]) ch[p][x]=np;
if(!p) ch[1][x]=np,pre[np]=1;
else
{
int q=ch[p][x];
if(mx[q]==mx[p]+1) pre[np]=q;
else
{
int nq=++tot; mx[nq]=mx[p]+1,R[nq]=R[q]-(mx[q]-mx[p]-1);
pre[nq]=pre[q],pre[np]=pre[q]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for(;p&&ch[p][x]==q;p=pre[p]) ch[p][x]=nq;
}
}
return np;
}
void dfs(int x)
{
p1[x]=++p2[0];
for(int i=0,y;i<10;i++) if((y=son[x][i])) dfs(y),siz[x]+=siz[y],mn[x]=min(mn[x],mn[y]);
p2[x]=p2[0];
}
inline void updata(int x)
{
for(int i=x;i<=tot;i+=i&-i) s[i]++;
}
inline int query(int x)
{
int ret=0,i;
for(i=x;i;i-=i&-i) ret+=s[i];
return ret;
}
int main()
{
scanf("%d%s",&n,S);
int i,j,x,y;
memset(mn,0x3f,sizeof(mn));
tot=last=1;
for(i=n-1;i>=0;i--) pos[i]=extend(S[i]-'0'),mn[pos[i]]=i,R[pos[i]]=n-1;
for(i=2;i<=tot;i++) L[i]=R[i]-(mx[i]-mx[pre[i]])+1,son[pre[i]][S[L[i]]-'0']=i;
scanf("%d",&m);
dfs(1);
R[1]=-1;
for(i=1;i<=m;i++)
{
scanf("%s",T),len[i]=strlen(T);
for(x=1,j=y=0;j<len[i];j++)
{
if(y<=R[x])
{
if(S[y]==T[j]) y++;
else break;
}
else
{
if(son[x][T[j]-'0']) x=son[x][T[j]-'0'],y=L[x]+1;
else break;
}
}
qos[i]=x;
if(j<len[i])
{
if(x==1) ans[i]=n;
else
{
ans[i]=n+1ll*siz[x]*min(mx[x]-mx[pre[x]],y-L[x]);
for(x=pre[x];x!=1;x=pre[x]) ans[i]+=1ll*(mx[x]-mx[pre[x]])*siz[x];
}
}
else
{
ans[i]=len[i]+mn[x];
if(mn[x]) q[mn[x]-1].push_back(i);
}
}
for(i=0;i<n;i++)
{
updata(p1[pos[i]]);
for(it=q[i].begin();it!=q[i].end();it++)
{
for(j=pre[qos[*it]];j;j=pre[j]) ans[*it]+=1ll*(mx[j]-mx[pre[j]])*(query(p2[j])-query(p1[j]-1));
}
}
for(i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}
【BZOJ3413】匹配 离线+后缀树+树状数组的更多相关文章
- BZOJ3413: 匹配(后缀自动机,Parent树,线段树合并)
Description Input 第一行包含一个整数n(≤100000). 第二行是长度为n的由0到9组成的字符串. 第三行是一个整数m. 接下来m≤5·10行,第i行是一个由0到9组成的字符串s, ...
- CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)
The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...
- 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组
题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...
- BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)
题目大意: 给你$n$个大串和$m$个询问,每次给出一个字符串$s$询问在多少个大串中出现过 好神的一道题 对$n$个大串建出广义$SAM$,建出$parent$树 把字符串$s$放到$SAM$里跑, ...
- Sereja and Brackets CodeForces - 380C (树状数组+离线)
Sereja and Brackets 题目链接: CodeForces - 380C Sereja has a bracket sequence s1, s2, ..., *s**n, or, in ...
- bzoj2743离线+树状数组
奇葩染色,对于每一个点关心的是前前个同颜色的位置,但是处理方法相同 离线比较神奇,按照右端点排序,然后每次用的是左端点,就不用建可持久化树状数组(什么鬼)了 区间修改+单点查询 果断差分以后用树状数组 ...
- BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]
1878: [SDOI2009]HH的项链 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 3486 Solved: 1738[Submit][Statu ...
- HDU 4605 Magic Ball Game (dfs+离线树状数组)
题意:给你一颗有根树,它的孩子要么只有两个,要么没有,且每个点都有一个权值w. 接着给你一个权值为x的球,它从更节点开始向下掉,有三种情况 x=w[now]:停在此点 x<w[now]:当有孩子 ...
- HDU3333 Turing Tree 树状数组+离线处理
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- 038改变状态栏的颜色(扩展知识:关于iOS不同版本的消息通知知识)
效果如下: ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController @e ...
- 表达式树(Expression Tree)
你每创建一个表示表达式的实例时,都可以将该类型实例看成是一棵表达式树.每种表示表达式的类型都有一个具体的类型,如Expression的Variable()方法创建的是ParameterExpressi ...
- MTK 隐藏上方的状态栏
步骤一: 源码/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.ja ...
- MySQL---insert into select from
INSERT INTO perf_week(node_id,perf_time,pm25,pm10,temp,humi) SELECT node_id,'2016-12-22 11:55:00' AS ...
- 7 -- Spring的基本用法 -- 10... 获取其他Bean的属性值;获取Field值;获取任意方法的返回值
7.10 高级依赖关系配置 组件与组件之间的耦合,采用依赖注入管理:但基本类型的成员变量值,应直接在代码中设置. Spring支持将任意方法的返回值.类或对象的Field值.其他Bean的getter ...
- [AX2012]在SSRS报表中获取从Menuitem传入的记录
在较早版本的AX中我们运行一个报表时会用到类RunBaseReport,从它扩展一个子类,再由它运行报表,一个典型的Axapta3中的例子: class ReportProdInfo extends ...
- C#反射基础理解1(转)
反射提供了封装程序集.模块和类型的对象(Type类型) 可以使用反射动态的创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后,可以调用类型的方法或访问其字段和属性 . 总之,有了反射, ...
- Windows下切换盘符
方法: 直接输入盘符+引号,例如输入D:,不区分大小写. 使用cd命令,例如cd /d D: 使用cd命令有一些要注意的地方: 在同一个磁盘分区里,不需要加上\d,但是不同磁盘分区切换的时候,需要加上 ...
- ARM入门最好的文章
一 首先说说arm的发展 可以用一片大好来形容,翻开各个公司的网站,招聘里面嵌入式占据了大半工程师职位.广义的嵌入式无非几种:传统的什么51.avr.pic称做嵌入式微控制器:arm是嵌入式微处理器 ...
- mybatis 之 parameterType="list"
<!-- 根据货品编号查找货品图片地址,货品ID,商品ID,货品名称 --> <select id="getGoodsInfoByGoodsNo" paramet ...