P4218 [CTSC2010]珠宝商


神题...

可以想到点分治,细节不写了。。。

(学了个新姿势,sam可以在前面加字符

但是一次点分治只能做到\(O(m)\),考虑\(\sqrt n\)点分治,如果子树大小\(>\sqrt n\)就用\(O(m)\)的点分治做法,否则用蛤希暴力。

然而块大小设为\(20,30\)比\(\sqrt n\)快多了...

#include<bits/stdc++.h>
#define il inline
#define vd void
#define frog 19260817
typedef long long ll;
typedef unsigned long long ull;
il ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))f^=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
#define qt 20
std::unordered_map<ull,int>qaq[50010/qt*2+1];
ull Base[50010];
int n,m;
ll ans;
char S[50010],T[50010];
int fir[50010],dis[100010],nxt[100010],id;
il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
int siz[50010],f[50010],FA[50010],N,rt;bool vis[50010];
struct SAM{
int slink[100010],trans[100010][26],pos[100010],son[100010][26],len[100010],endpos[100010],cnt,lst,leaf[50010],flg;
char ss[100010];
SAM(){cnt=0;lst=++cnt;len[lst]=0;}
il vd extend(int ch,int i){
int p=lst,np=++cnt;len[np]=len[p]+1;lst=np;endpos[np]=1;leaf[i]=np;pos[np]=i;
while(p&&!trans[p][ch])trans[p][ch]=np,p=slink[p];
if(!p)slink[np]=1;
else{
int q=trans[p][ch];
if(len[q]==len[p]+1)slink[np]=q;
else{
int nq=++cnt;
slink[nq]=slink[q],len[nq]=len[p]+1,memcpy(trans[nq],trans[q],sizeof trans[q]);
while(p&&trans[p][ch]==q)trans[p][ch]=nq,p=slink[p];
slink[np]=slink[q]=nq;
}
}
}
int t[100010],st[100010];
il vd prepare(){
for(int i=1;i<=m;++i)ss[i]=S[i];
for(int i=1;i<=cnt;++i)++t[len[i]];
for(int i=1;i<=cnt;++i)t[i]+=t[i-1];
for(int i=cnt;i>1;--i)st[t[len[i]]--]=i;
for(int i=cnt,x;i;--i){
x=st[i];endpos[slink[x]]+=endpos[x];
if(!pos[slink[x]])pos[slink[x]]=pos[x];
if(pos[x]-len[slink[x]])son[slink[x]][ss[pos[x]-len[slink[x]]]-'a']=x;
}
}
int tag[100010];
il vd calc(){
for(int i=1,x;i<=cnt;++i)x=st[i],tag[x]+=tag[slink[x]];
}
il vd dfs3(int x,int fa,int y,int _len){
if(_len==len[y])y=son[y][T[x]-'a'];
else if(ss[pos[y]-_len]!=T[x])y=0;
if(!y)return;
++tag[y];++_len;
//printf("%d %d %d %d\n",x,fa,y,_len);
for(int i=fir[x];i;i=nxt[i]){
if(fa==dis[i]||vis[dis[i]])continue;
dfs3(dis[i],x,y,_len);
}
}
}sam,rsam;
il vd getrt(int x,int fa=-1){
siz[x]=1,f[x]=0;
for(int i=fir[x];i;i=nxt[i]){
if(fa==dis[i]||vis[dis[i]])continue;
FA[dis[i]]=x;
getrt(dis[i],x);
siz[x]+=siz[dis[i]];
f[x]=std::max(f[x],siz[dis[i]]);
}
f[x]=std::max(f[x],N-siz[x]);
if(f[rt]>f[x])rt=x;
}
std::vector<int>G;
il vd dfs(int x,int fa=-1){
G.push_back(x);
for(int i=fir[x];i;i=nxt[i]){
if(fa==dis[i]||vis[dis[i]])continue;
dfs(dis[i],x);
}
}
il vd dfs2(int x,int y,int fa=-1){
if(!y)return;
ans+=sam.endpos[y];
for(int i=fir[x];i;i=nxt[i]){
if(fa==dis[i]||vis[dis[i]])continue;
dfs2(dis[i],sam.trans[y][T[dis[i]]-'a'],x);
}
}
std::vector<ull>A,B;
std::vector<int>LA,LB;
il vd dfs2_(int x,ull HA,ull HB,int len,int fa=-1){
HA=(HA+T[x])*frog,HB+=Base[++len]*T[x];
A.push_back(HA),LA.push_back(len+1),B.push_back(HB),LB.push_back(len);
for(int i=fir[x];i;i=nxt[i]){
if(fa==dis[i]||vis[dis[i]])continue;
dfs2_(dis[i],HA,HB,len,x);
}
}
il vd work(int x,int fa,ll o){
if(siz[x]<=qt){
A.clear(),B.clear();LA.clear();LB.clear();
dfs2_(x,(ull)frog*T[fa],0,0,fa);
for(int i=0;i<A.size();++i)
for(int j=0;j<B.size();++j){
ull H=A[i]+B[j]*Base[LA[i]];
if(qaq[LA[i]+LB[j]].count(H))ans+=o*qaq[LA[i]+LB[j]][H];
}
return;
}
memset(sam.tag,0,(sam.cnt+1)*4);memset(rsam.tag,0,(rsam.cnt+1)*4);
if(fa)sam.dfs3(x,fa,sam.son[1][T[fa]-'a'],1),rsam.dfs3(x,fa,rsam.son[1][T[fa]-'a'],1);
else sam.dfs3(x,fa,1,0),rsam.dfs3(x,fa,1,0);
sam.calc(),rsam.calc();
for(int i=1;i<=m;++i)ans+=o*sam.tag[sam.leaf[i]]*rsam.tag[rsam.leaf[m-i+1]];
}
il vd solve(int x){
if(siz[x]<=qt){
G.clear();dfs(x);
for(int i:G)dfs2(i,sam.trans[1][T[i]-'a']);
for(int i:G)vis[i]=1;
return;
}
work(x,0,1);
vis[x]=1;
for(int i=fir[x];i;i=nxt[i]){
if(vis[dis[i]])continue;
work(dis[i],x,-1);
}
for(int i=fir[x];i;i=nxt[i]){
if(vis[dis[i]])continue;
rt=0,N=siz[dis[i]],getrt(dis[i]),solve(rt);
}
}
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
sam.flg=1,rsam.flg=0;
n=gi(),m=gi();int a,b;
for(int i=1;i<n;++i)a=gi(),b=gi(),link(a,b),link(b,a);
scanf("%s",T+1),scanf("%s",S+1);
Base[0]=1;for(int i=1;i<=m;++i)Base[i]=Base[i-1]*frog;
for(int i=1;i<=m;++i){
ull Hash=0;
for(int j=1;i+j-1<=m&&j<=qt*2+1;++j)Hash+=Base[j]*S[i+j-1],++qaq[j][Hash];
}
for(int i=1;i<=m;++i)sam.extend(S[i]-'a',i);
sam.prepare();
std::reverse(S+1,S+m+1);
for(int i=1;i<=m;++i)rsam.extend(S[i]-'a',i);
rsam.prepare();
std::reverse(S+1,S+m+1);
N=n;f[0]=1e9,rt=0,getrt(1),solve(rt);
printf("%lld\n",ans);
return 0;
}

P4218 [CTSC2010]珠宝商的更多相关文章

  1. 洛谷P4218 [CTSC2010]珠宝商(后缀自动机+点分治)

    传送门 这题思路太清奇了……->题解 //minamoto #include<iostream> #include<cstdio> #include<cstring ...

  2. [CTSC2010]珠宝商 SAM+后缀树+点分治

    [CTSC2010]珠宝商 不错的题目 看似无法做,n<=5e4,8s,根号算法? 暴力一: n^2,+SAM上找匹配点的right集合sz,失配了直接退出 暴力二: O(m) 统计过lca=x ...

  3. CTSC2010 珠宝商

    珠宝商 题目描述 Louis.PS 是一名精明的珠宝商,他出售的项链构造独特,很大程度上是因为他的制作方法与众不同.每次 Louis.PS 到达某个国家后,他会选择一条路径去遍历该国的城市.在到达一个 ...

  4. [BZOJ1921] [CTSC2010]珠宝商

    Description Input 第一行包含两个整数 N,M,表示城市个数及特征项链的长度. 接下来的N-1 行, 每行两个整数 x,y, 表示城市 x 与城市 y 有直接道路相连.城市由1~N进行 ...

  5. @bzoj - 1921@ [ctsc2010]珠宝商

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 简述版题意:给定字符串 S 与一棵树 T,树上每个点有一个字符. ...

  6. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  7. Sam做题记录

    Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...

  8. 【BZOJ1921】【CTSC2010】珠宝商(点分治,后缀自动机)

    [BZOJ1921][CTSC2010]珠宝商(点分治,后缀自动机) 题面 洛谷 BZOJ权限题 题解 如果要我们做暴力,显然可以以某个点为根节点,然后把子树\(dfs\)一遍,建出特征串的\(SAM ...

  9. CTSC2010

    星际旅行 https://www.luogu.com.cn/problem/P4189 题目:且每个星球的\(H_i\)大于等于与该星球直接相连的星球数(即度数). 想到先从根到所有点都走一遍,然后贪 ...

随机推荐

  1. IQueryable,IEnumerable,IList区别

    IQueryable和IEnumerable都是延时执行(Deferred Execution)的,而IList是即时执行(Eager Execution)IQueryable和IEnumerable ...

  2. (转).NET Core中实现AOP编程

    原文地址:https://www.cnblogs.com/xiandnc/p/10088159.html AOP全称Aspect Oriented Progarmming(面向切面编程),其实AOP对 ...

  3. 小程序加入echart 图表

    github上的地址 https://github.com/ecomfe/echarts-for-weixin 复制到当前项目根目录下 添加展示bar图表例子的文件夹 index.json 中配置使用 ...

  4. kali之HexorBase数据库破解

    HexorBase 用户名密码连接数据库 暴力破解 点击底栏 Bruteforces Databases Servers , 然后会弹出一个新界面 Databases Bruteforces 新界面  ...

  5. vue中is与:is的区别

    简略回答 假设父组件中有一个show数据,show="one":is="show"-->实际上是is="one" is="s ...

  6. Excel内部编码查看与验证工具

    Excel 2007 以前版本 MS-XLS内部结构:BIFF格式 https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms- ...

  7. postman 在pre-request中发送application/x-www-form-urlencoded 格式表单

    postman中在pre-request 发送请求 知识点: json数据解析和遍历 application/x-www-form-urlencoded表单 Array基本使用 js函数 http请求 ...

  8. 【等待事件】等待事件系列(3+4)--System IO(控制文件)+日志类等待

     [等待事件]等待事件系列(3+4)--System IO(控制文件)+日志类等待   1  BLOG文档结构图     2  前言部分   2.1  导读和注意事项 各位技术爱好者,看完本文后,你可 ...

  9. MySQL Replication--半同步复制(Semi-Sync Replication)

    半同步复制 默认配置下,MYSQL主从库通过binlog来保持一致,主库事务提交后,将binlog日志写入磁盘,然后返回给用户,备库通过拉取主库的binlog来同步主库的操作,无法保证主备节点数据实时 ...

  10. windows 任务计划

    我的需求是每天定时访问网站的某一个控制器去刷新库存 流程如下(我自己的理解) 进入任务计划页面 上图指定的bat文件内容就是访问指定的网站路径 dingshi.bat文件内容如下(这个是网上找的,可能 ...