传送门

题解:
点分治,如果点数≥n\ge \sqrt{n}≥n​,则结合后缀树O(sze+m)O(sze+m)O(sze+m)处理出每个位置的开始,结束点并统计答案。否则从每个点开始暴力扩展路径。

时间复杂度O(nn)O(n \sqrt{n})O(nn​)。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
typedef long long LL;inline int rd() {char ch=getchar(); int i=0,f=1;while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}return i*f;
}const int N=1e5+50, B=150;
int n,m,mx,total,G,fa[N];
int sze[N],c1[N],c2[N],vis[N];
char s[N];
long long ans;
vector <int> edge[N];struct sam {char ch[N];int last,tot;int pos[N],son[N][26],tr[N][26],fail[N],len[N];int c[N],q[N];vector <int> edge[N];sam() {last=tot=1;}inline void extend(int c,int op) {int p=++tot; len[p]=len[last]+1; pos[p]=op;for(;last && !son[last][c];last=fail[last]) son[last][c]=p;if(!last) fail[p]=1;else {int q=son[last][c];if(len[q]==len[last]+1) fail[p]=q;else {int np=++tot; len[np]=len[last]+1; pos[np]=pos[q];memcpy(son[np],son[q],sizeof(son[np]));fail[np]=fail[q]; fail[q]=fail[p]=np;for(;last && son[last][c]==q;last=fail[last]) son[last][c]=np;}} last=p;}inline void init() {for(int i=1;i<=m;i++) extend(ch[i]-'a',i);for(int i=1;i<=tot;i++) if(fail[i]) edge[fail[i]].push_back(i);for(int i=1;i<=tot;i++) ++c[len[i]];for(int i=1;i<=tot;i++) c[i]+=c[i-1];for(int i=tot;i>=1;i--) q[c[len[i]]--]=i;memset(c,0,sizeof(c));for(int i=tot;i>=1;i--) {int u=q[i];if(pos[u]==len[u]) ++c[u];if(fail[u]) c[fail[u]]+=c[u];}for(int i=1;i<=tot;i++) {int u=q[i];for(int e=0,v;e<edge[u].size() && (v=edge[u][e]);++e)tr[u][ch[pos[v]-len[u]]-'a']=v;}memset(q,0,sizeof(q));}inline pii trans(pii p,char c) {if(!p.first) return pii(0,0);else if(p.second==len[p.first]) return pii(tr[p.first][c-'a'],p.second+1);else {if(ch[pos[p.first]-p.second]==c) return pii(p.first,p.second+1);else return pii(0,0);}}inline int trans2(int p,char c) {return son[p][c-'a'];}inline void add(pii p) {++q[p.first];}
} ori,rev;inline void calcG(int x,int f) {sze[x]=1;  int mx_son=0;for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e)if(!vis[v] && v!=f) {calcG(v,x);sze[x]+=sze[v];mx_son=max(mx_son,sze[v]);}mx_son=max(mx_son,total-sze[x]);if(mx_son<=mx) mx=mx_son, G=x;
}inline void dfs(int x,int f,pii p1,pii p2) {p1=ori.trans(p1,s[x]); p2=rev.trans(p2,s[x]);ori.add(p1); rev.add(p2); sze[x]=1;for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e)    if(!vis[v] && v!=f) {dfs(v,x,p1,p2);       sze[x]+=sze[v];}
}
inline void dfs(sam &t,int x,int sum,int flag) {sum+=t.q[x];if(t.pos[x]==t.len[x]) (flag ? c2[m-t.pos[x]+1] : c1[t.pos[x]])+=sum;;for(int e=0,v;e<t.edge[x].size() && (v=t.edge[x][e]);++e) dfs(t,v,sum,flag);
}int rt;
inline void dfs3(int x,int f,int p,int flag) {if(!p) return;ans+=flag*ori.c[p];for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e) if(!vis[v] && v!=f) dfs3(v,x,ori.trans2(p,s[v]),flag);
}
inline void dfs2(int x,int f,int flag) {int p=1;if(flag<0) {for(int i=x;;i=fa[i]) {p=ori.trans2(p,s[i]); if(i==rt) break;}p=ori.trans2(p,s[G]); } if(flag<0) dfs3(rt,0,ori.trans2(p,s[rt]),flag);else dfs3(x,0,ori.trans2(p,s[x]),flag);for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e) if(!vis[v] && v!=f) dfs2(v,x,flag);
}
inline void force_solve(int x,int flag) {rt=x; dfs2(x,0,flag);
}
inline void calc1(int t) {for(int i=1;i<=m;i++) c1[i]=c2[i]=0;dfs(ori,1,0,0); dfs(rev,1,0,1);for(int i=1;i<=m;i++) ans+=(LL)c1[i]*c2[i]*t;for(int i=1;i<=ori.tot;i++) ori.q[i]=0;for(int i=1;i<=rev.tot;i++) rev.q[i]=0;
}
inline void calc2(int x) {if(sze[x]<=B) {force_solve(x,-1);} else {pii p(1,0);dfs(x,G,ori.trans(p,s[G]),rev.trans(p,s[G]));calc1(-1);}
}
inline void dfs_pre(int x,int f) {fa[x]=f; for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e) if(!vis[v] && v!=f) dfs_pre(v,x);}
inline void solve(int x) {if(total<=B) force_solve(x,1);else {pii p(1,0); vis[x]=1;ori.add(ori.trans(p,s[x]));rev.add(rev.trans(p,s[x]));for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e)if(!vis[v]) dfs_pre(v,x), dfs(v,x,ori.trans(p,s[x]),rev.trans(p,s[x]));calc1(1);for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e)if(!vis[v]) calc2(v);for(int e=0,v;e<edge[x].size() && (v=edge[x][e]);++e) if(!vis[v]) {mx=total=sze[v];calcG(v,x);solve(G);}}
}
int main() {n=rd(), m=rd();for(int i=1;i<n;i++) {int x=rd(), y=rd();edge[x].push_back(y);edge[y].push_back(x);} scanf("%s",s+1);scanf("%s",ori.ch+1);reverse_copy(ori.ch+1,ori.ch+m+1,rev.ch+1);ori.init(); rev.init();mx=total=n; calcG(1,0);solve(G);cout<<ans<<'\n';
}

BZOJ1921: [Ctsc2010]珠宝商(点分治+SAM)相关推荐

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

    Description 有一棵n个节点的树和一个长度为m的字符串S,树上每个节点有一个字符.问对于任意的有序数对(x,y),从x到y路径组成的字符串在S中出现次数的和. n,m≤5⋅104n,m\le ...

  2. BZOJ 1921: [Ctsc2010]珠宝商 点分治套SAM

    题目链接 首先可以发现两种算法 一. 暴力处理 对"特征串"建SAM 枚举路径的一个端点,\(dfs\)另一个端点,同时维护在SAM上的位置. 每到一个位置会有SAM上对应节点的r ...

  3. [BZOJ1921] [CTSC2010]珠宝商

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

  4. bzoj1921: [Ctsc2010]珠宝商

    暴毙选手又被zo老师D费了 暴力是n^2的都会 有另一个点分的做法,就是看成两条链,然后在后缀树上跑,找到对应原串位置拼起来,是n*(logn+m) 然后就根号分治,树的大小超过阈值就点分,小于就暴力 ...

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

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

  6. [CTSC2010]珠宝商(点分治+根号分治+后缀自动机)

    [CTSC2010]珠宝商 洛谷题目传送门 简要题意 给定一颗nnn个节点的树,和一个长度为mmm的模式串SSS 树上每个节点都有一个字符 求树上所有路径的点的字符拼成的字符串在SSS中的出现次数之和 ...

  7. bzoj 1921: [Ctsc2010]珠宝商

    题意: 给一棵树,每个点上有一个字母,问对于所有(x,y),求x到y的路径所组成的字符串在S中出现次数的和. 题解: 先上题解:begined CTSC2010 珠宝商新解 然后说说个人的垃圾理解. ...

  8. P4218 [CTSC2010]珠宝商

    P4218 [CTSC2010]珠宝商 神题... 可以想到点分治,细节不写了... (学了个新姿势,sam可以在前面加字符 但是一次点分治只能做到\(O(m)\),考虑\(\sqrt n\)点分治, ...

  9. bzoj1921 CTSC2010 jewelry

    大概是四节课写代码,三节课debug,七个长相差不多的dfs穿插其中-- 好了不吐槽了: 题意: 给定一棵点上有字母的树,和一个母串 求树上点两两之间 N2N^2 条路径在母串中匹配次数和 这里采用的 ...

最新文章

  1. C/C++中static关键字用法汇总
  2. win 10升级后不能访问服务器文件夹,Win10打开某些文件夹出现“无法访问”的解决方法...
  3. 重写enum的valueof方法等
  4. unity三维向量变化为角度_对于向量和矩阵的理解
  5. 重构机房VB.NET机房收费系统个人重构版你都学会了什么(之一)
  6. JSP之EL表达式详细介绍
  7. sql2008“备份集中的数据库备份与现有的xx数据库不同”解决方法 因为是在另一台电脑对同名数据库做的备份,用常规方法还原,提示不是相同数据库,不让还原,在网上找到下面的方法解决了: 一、右击系
  8. 2万字!66道并发面试题及答案
  9. c语言跳至表域跳几个字符,c语言学习最好资料.doc
  10. Spring解析 XML 的原理,你搞定了么?
  11. gpt分区安装的Win7激活工具
  12. Oracle BI系统排名?Oracle BI办公系统怎么选?什么是用户口碑最好的Oracle BI系统?
  13. 一个骨灰级塞班开发者的自白
  14. 两层板如何做阻抗控制呢
  15. Java习题练习:杨辉三角
  16. PhpSpreadsheet读取excel
  17. 基于51单片机实现计算器功能
  18. 写论文的工具推荐(包括下载论文,写作,翻译等)
  19. 毕设 JAVA.JSP二手车交易系统论文
  20. Lemon评测机的使用

热门文章

  1. win10怎么把两个盘合成一个,win10怎么把分区合并
  2. 《树莓派项目实战》第五节 使用Nokia 5110液晶屏显示Hello World
  3. win10专业版有必要吗_Win10自带Windows defender 还有必要安装其它杀毒软件吗?
  4. 平台交叉打包 GYP
  5. 怎样做音乐相册?简单又好看的音乐相册怎么做?
  6. oracle的job引起数据库崩溃,JOB忽然停止工作了
  7. 定积分之几种常见曲线
  8. U8固定资产最重要的数据表
  9. PLC培训班一般多少钱?
  10. Pinia——Actions