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. Selenium+Java(八)Selenium下拉框处理

    Selenium定位下拉框中的元素与普通元素定位有所不同,下面介绍三种定位下拉框元素的方法. 下拉款HTML代码如图所示: 一.通过text定位 //获取下拉框对象 Select city = new ...

  2. 笔记:npm常见错误

    常见错误 破坏的npm安装 随机错误 找不到兼容版本 权限错误 Error: ENOENT, stat 'C:\Users\<user>\AppData\Roaming\npm' 在Win ...

  3. 转:使用Goproxy解决golang.org模块无法下载的问题

    原文https://studygolang.com/articles/22277?fr=sidebar 简介 Goproxy 中国完全实现了 Go 的模块代理协议.并且它是一个由中国备受信赖的云服务提 ...

  4. mysql中length与char_length字符长度函数使用方法

    在mysql中length是计算字段的长度一个汉字是算三个字符,一个数字或字母算一个字符了,与char_length是有一点区别,本文章重点介绍第一个函数. mysql里面的length函数是一个用来 ...

  5. Java Annontation 注解的学习和理解

    /** * <html> * <body> * <P> Copyright 1994 JsonInternational</p> * <p> ...

  6. shell 遍历目录下的所有文件

    dir=/usr/local/nginx/logs for file in $dir/*; do echo $file done //结果 ./test.sh /usr/local/nginx/log ...

  7. testNG helloWorld

    1. 新建maven工程.File -> New -> Project -> Maven,不选Create from archetype,直接点击“Next”.GroupId和Art ...

  8. 【快捷键】印象笔记Markdown快捷键

    新建 Markdown 笔记 CMD+D 粗体 CMD+B 斜体 CMD+I 删除线 CMD+S 分隔线 CMD+L 编号列表 CMD+Shift+O 项目符号列表 CMD+Shift+U 插入待办事 ...

  9. ZMQ应用

    一.  ZeroMQ概述 ZeroMQ是一种基于消息队列的多线程网络库,其对套接字类型.连接处理.帧.甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字.ZeroMQ是网络通信中新的一层,介于应 ...

  10. python笔记--------一

    作用域: 每个变量或函数都有自己的作用域. 每个函数都定义了一个命名空间,也称为作用域. 在最顶层有一个符号表会跟踪这一层所有的名称定义和和他们当前的绑定. 调用函数时,会建立一个新的符号表(常称为栈 ...