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\)大于等于与该星球直接相连的星球数(即度数). 想到先从根到所有点都走一遍,然后贪 ...
随机推荐
- Java字节码扩展
异常表 代码一: public class Test03 { public void test() { try { InputStream is = new FileInputStream(" ...
- SQL Server——死锁查看
一.通过语句查看 --查询哪些死锁SELECT request_session_id spid, OBJECT_NAME( resource_associated_entity_id ) tableN ...
- MVC中根据后台绝对路径读取图片并显示在IMG中
数据库存取图片并在MVC3中显示在View中 根据路径读取图片: byte[] img = System.IO.File.ReadAllBytes(@"d:\xxxx.jpg"); ...
- port: ${SERVER_PORT:9190} #首先取环境变量,如果环境变量中没有,就取 9190 这个固定值
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'spring.datas ...
- php学习笔记——学习路线图记录
PHP学习路线图 最全PHP自学指南 W3Cschool小编 2018-04-24 15:23:51 浏览数 (5381) 分享 收录专辑 对于广大零基础的PHP自学者,往往不知道如何系统的学习PHP ...
- 令人兴奋的TOP Server OPC Server v6.5 五大功能(上)
Software Toolbox的OPC和原生HMI设备的连接软件:TOP Server OPC Server.TOP Server OPC Server是采用业界领先的Kepware技术的工业4.0 ...
- Java 递归方法
递归:在一个方法体内,调用自身,一般要有出口. 实例:已知一个数列,f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),其中n为大于等于0的整数,求f(10)的值. package ...
- 攻防世界WEB高手进阶之Zhuanxv
1.一开始就是一个时钟界面 2.扫描目录发现/list 目录 打开是后台登陆,看了一下源码,也没发现什么,焦灼... 3.百度上搜了一波wp,发现原来在css里面藏了东西 后台的背景图片居然是这样读取 ...
- 哈希长度拓展攻击之De1CTF - SSRF Me
题目考查:python代码审计.hash长度拓展攻击 0x01 题目源码: #! /usr/bin/env python #encoding=utf-8 from flask import Flask ...
- 洛谷 P2384 最短路题解
题目背景 狗哥做烂了最短路,突然机智的考了Bosh一道,没想到把Bosh考住了...你能帮Bosh解决吗? 他会给你100000000000000000000000000000000000%10金币w ...