P4218 [CTSC2010]珠宝商
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]珠宝商的更多相关文章
- 洛谷P4218 [CTSC2010]珠宝商(后缀自动机+点分治)
传送门 这题思路太清奇了……->题解 //minamoto #include<iostream> #include<cstdio> #include<cstring ...
- [CTSC2010]珠宝商 SAM+后缀树+点分治
[CTSC2010]珠宝商 不错的题目 看似无法做,n<=5e4,8s,根号算法? 暴力一: n^2,+SAM上找匹配点的right集合sz,失配了直接退出 暴力二: O(m) 统计过lca=x ...
- CTSC2010 珠宝商
珠宝商 题目描述 Louis.PS 是一名精明的珠宝商,他出售的项链构造独特,很大程度上是因为他的制作方法与众不同.每次 Louis.PS 到达某个国家后,他会选择一条路径去遍历该国的城市.在到达一个 ...
- [BZOJ1921] [CTSC2010]珠宝商
Description Input 第一行包含两个整数 N,M,表示城市个数及特征项链的长度. 接下来的N-1 行, 每行两个整数 x,y, 表示城市 x 与城市 y 有直接道路相连.城市由1~N进行 ...
- @bzoj - 1921@ [ctsc2010]珠宝商
目录 @description@ @solution@ @accepted code@ @details@ @description@ 简述版题意:给定字符串 S 与一棵树 T,树上每个点有一个字符. ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- Sam做题记录
Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...
- 【BZOJ1921】【CTSC2010】珠宝商(点分治,后缀自动机)
[BZOJ1921][CTSC2010]珠宝商(点分治,后缀自动机) 题面 洛谷 BZOJ权限题 题解 如果要我们做暴力,显然可以以某个点为根节点,然后把子树\(dfs\)一遍,建出特征串的\(SAM ...
- CTSC2010
星际旅行 https://www.luogu.com.cn/problem/P4189 题目:且每个星球的\(H_i\)大于等于与该星球直接相连的星球数(即度数). 想到先从根到所有点都走一遍,然后贪 ...
随机推荐
- maven的setting配置文件中mirror和repository的区别
当maven需要到的依赖jar包不在本地仓库时, 就需要到远程仓库下载 . 这个时候如果mavensetting.xml中配置了镜像 , 而且镜像配置的规则中匹配到目标仓库时 , maven认为目标仓 ...
- java Unicode和UTF-8之间转换
utf-8转unicode public static String utf8ToUnicode(String inStr) { char[] myBuffer = inStr.toCharArray ...
- git设置代理模式,仅为github设置代理
设置代理: 全局代理 git config --global http.proxy 127.0.0.1:1087 局部代理,在github clone 仓库内执行 git config --local ...
- KIP-382: MirrorMaker 2.0
Status Motivation Public Interfaces Proposed Changes Remote Topics, Partitions Aggregation Cycle det ...
- C# vb .net实现移除像素特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的移除像素特效呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- C# vb .net实现位图蒙版特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的位图蒙版特效呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- CSP J/S 2019受虐记
一枚蒟蒻的游记~ 提高组DAY1 不是说每场考试都有一道签到题吗 那我tm读了三遍题硬是没找到一道水题是怎么回事(是我太弱了吗) 没办法,硬着头皮做T1 暴力写法...期望得分30pts 于是...在 ...
- 十大Intellij IDEA快捷键(附IDEA快捷键详细列表及使用技巧)
十大Intellij IDEA快捷键(附IDEA快捷键详细列表及使用技巧) Intellij IDEA中有很多快捷键让人爱不释手,stackoverflow上也有一些有趣的讨论.每个人都有自己的最爱, ...
- 微信小程序代码开源啦
想学习如何使用mpvue开发微信小程序吗? 想知道微信消息推送如何实现吗? 想知道如何用springboot开发小程序后台吗? 看这里就全都有了.耗时一个月打造的微信小程序:PSN折扣助手前后端所有源 ...
- 反序列化之PHP原生类的利用
目录 基础知识 __call SoapClient __toString Error Exception 实例化任意类 正文 文章围绕着一个问题,如果在代码审计中有反序列化点,但是在原本的代码中找不到 ...