Description
给定一个n个点的树,树上每个点有一个字符,再给一个长度为m的串。
两点的价值为:两点连接形成的字符串再m串中出现的次数。
询问两两点价值的和。


Sample Input
3 5
1 2
1 3
aab
abaab


Sample Output
15


首先考虑点分治。
然后再考虑根号分治
对于一个点分治块,假如它的大小小于等于n\sqrt nn​,那么直接对于每一个点暴力去做它可以形成的所有串,可以用自动机在dfs中O(1)O(1)O(1)维护一个串出现的次数。
这一部分时间复杂度不超过O(nn)O(n\sqrt n)O(nn​)。
对于大于等于n\sqrt nn​的块,我们只用考虑经过分治中心的点即可。
对于一条路径(x,y),设分治中心为g,则我们考虑对于一个m串中的位置p的贡献。我们算出(x,g)经过了p的次数,(g,y)经过了p的次数,相乘即可。
先考虑(x,g),我们可以建出一个parent树,从g往下走,就相当于每次都在前面插个字符,那就相当于直接在parent树上走,边走边打标记,最后再跑一边parent树累加标记即可。
对于(g,y)就相当于在后缀树上做。
因为所有这样的块不超过n\sqrt nn​个,所以这样的时间复杂度为O(nn)O(n\sqrt n)O(nn​)。


#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>using namespace std;
typedef long long LL;
const int N = 100010;
int _max(int x, int y) {return x > y ? x : y;}
int _min(int x, int y) {return x < y ? x : y;}
int read() {int s = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();return s * f;
}struct edge {int x, y, next;
} e[2 * N]; int len, n, m, last[N];
char yy[N], tt[N];
bool v[N];
struct SAM {int cnt, lst, fa[N * 2], len[N * 2], right[N * 2], ch[N * 2][26], son[N * 2][26];int s[N], size[N], id[N * 2], ss[N], tag[N];void ins(int c, int i) {int np = ++cnt, p = lst; ss[i] = c;len[np] = len[p] + 1; right[np] = i; size[np] = 1;while(p && !ch[p][c]) ch[p][c] = np, p = fa[p];if(!p) fa[np] = 1;else {int q = ch[p][c];if(len[p] + 1 == len[q]) fa[np] = q;else {int nq = ++cnt;fa[nq] = fa[q]; len[nq] = len[p] + 1;memcpy(ch[nq], ch[q], sizeof(ch[nq]));fa[np] = fa[q] = nq;while(p && ch[p][c] == q) ch[p][c] = nq, p = fa[p];}} lst = np;}void bt() {for(int i = 1; i <= cnt; i++) ++s[len[i]];for(int i = 1; i <= m; i++) s[i] += s[i - 1];for(int i = cnt; i >= 1; i--) id[s[len[i]]--] = i;for(int i = cnt; i >= 1; i--) {int x = id[i], F = fa[x];size[F] += size[x];right[F] = _max(right[F], right[x]);son[F][ss[right[x] - len[F]]] = x;}}void work(int x, int fa, int now, int ll) {if(ll == len[now]) now = son[now][tt[x]];else if(ss[right[now] - ll] != tt[x]) now = 0;if(!now) return ; ++tag[now];for(int k = last[x]; k; k = e[k].next) {int y = e[k].y;if(y != fa && !v[y]) work(y, x, now, ll + 1);}}void push() {for(int i = 1; i <= cnt; i++) tag[id[i]] += tag[fa[id[i]]];}
} sam1, sam2;
int sum, block, tot[N], f[N];
int tp, now, sta[N];
int id1[N], id2[N];
LL ans;void ins(int x, int y) {e[++len].x = x, e[len].y = y;e[len].next = last[x], last[x] = len;
}int getrt(int x, int fa) {int p = 0;tot[x] = 1; f[x] = 0;for(int k = last[x]; k; k = e[k].next) {int y = e[k].y;if(y != fa && !v[y]) {int hh = getrt(y, x);if(f[hh] < f[p]) p = hh;tot[x] += tot[y];f[x] = _max(f[x], tot[y]);}} f[x] = _max(f[x], sum - tot[x]);if(f[x] < f[p]) p = x;return p;
}void get(int x, int fa) {sta[++tp] = x;for(int k = last[x]; k; k = e[k].next) {int y = e[k].y;if(y != fa && !v[y]) get(y, x);}
}void getsum(int x, int fa) {if(!now) return ;int hh = now; ans += sam1.size[now];for(int k = last[x]; k; k = e[k].next) {int y = e[k].y;if(y != fa && !v[y]) {now = sam1.ch[now][tt[y]], getsum(y, x);now = hh;}}
}void calc(int x, int fa, int o) {for(int i = 1; i <= sam1.cnt; i++) sam1.tag[i] = 0;for(int i = 1; i <= sam2.cnt; i++) sam2.tag[i] = 0;if(o == 1) sam1.work(x, 0, 1, 0), sam2.work(x, 0, 1, 0);else sam1.work(x, 0, sam1.son[1][tt[fa]], 1), sam2.work(x, 0, sam2.son[1][tt[fa]], 1);sam1.push(), sam2.push();for(int i = 1; i <= m; i++) ans += (LL)o * sam1.tag[id1[i]] * sam2.tag[id2[m - i + 1]];
}void solve(int x) {if(sum <= block) {tp = 0; get(x, 0);for(int i = 1; i <= tp; i++) now = sam1.ch[1][tt[sta[i]]], getsum(sta[i], 0);return ;} v[x] = 1;calc(x, 0, 1);for(int k = last[x]; k; k = e[k].next) {int y = e[k].y;if(!v[y]) {calc(y, x, -1);sum = tot[y], solve(getrt(y, 0));}}
}int main() {n = read(), m = read();for(int i = 1; i < n; i++) {int x = read(), y = read();ins(x, y), ins(y, x);} scanf("%s", tt + 1);scanf("%s", yy + 1);sam1.cnt = sam2.cnt = sam1.lst = sam2.lst = 1;for(int i = 1; i <= m; i++) yy[i] -= 'a', sam1.ss[i] == yy[i], sam1.ins(yy[i], i), id1[i] = sam1.lst;reverse(yy + 1, yy + m + 1);for(int i = 1; i <= m; i++) sam2.ss[i] == yy[i], sam2.ins(yy[i], i), id2[i] = sam2.lst;sam1.bt(), sam2.bt();f[0] = 999999999; block = sqrt(n);for(int i = 1; i <= n; i++) tt[i] -= 'a';sum = n, solve(getrt(1, 0));printf("%lld\n", ans);return 0;
}

[Ctsc2010]珠宝商 SAM+点分治+根号分治相关推荐

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

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

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

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

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

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

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

    传送门 这题思路太清奇了--->题解 1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include< ...

  5. [HDU 6643] Ridiculous Netizens(点分治+根号分治+dp)

    HDU 6643 Ridiculous Netizens problem hdu6643 题目大意:给定一棵无根树,以及每个点的点权 wiw_iwi​. 定义一个连通块的价值为连通块内点的点权之积. ...

  6. 浅谈根号分治——暴力的美学

    根号分治 根号分治的概念 [模板]P3396 哈希冲突 CF103D Time to Raid Cowavans 根号分治的概念 根号分治是一种优化暴力算法. 我个人的理解就是这东西跟分块差不多.但应 ...

  7. 学习计划——根号分治

    根号分治 根号分治是一种思想,一般根据一个数(可以是数组的数,也可以是答案的数)分类,分为大于 s q r t ( n ) sqrt(n) sqrt(n)的部分和小于等于 s q r t ( n ) ...

  8. 【CTSC2010】珠宝商【后缀自动机】【点分治】【根号分治】

    题意:给一棵 nnn 个点的树,每个点有个字符,另给一个长度为 mmm 的特征串,求树上 n2n^2n2 条有向路径在特征串中出现的次数之和. n,m≤5×104n,m\leq 5\times 10^ ...

  9. 树链剖分 or 根号分治 + dfs序 + 树状数组 ---- CF1254 D. Tree Queries

    题目链接 题目大意: 问题转化: 很容易发现:假设修改的节点是vvv. 1.vvv的子树sonvson_vsonv​直接加上(n−size[sonv])n×d\frac{(n-size[son_v]) ...

最新文章

  1. gradlew 的https代理设定
  2. QT的QFileSelector类的使用
  3. at org.apache.coyote.http11.AbstractOutputBuffer.checkLengthBeforeWrite
  4. 【玩转Eclipse】——eclipse实现代码块折叠-类似于VS中的#region……#endregion
  5. 1 元购买 1000+ 册爆款电子书,错过再等一年!
  6. freeswitch新增app接口
  7. LINUX下载编译gperf
  8. 设计模式讲解2:static proxy和decorator的不同点
  9. quartus支持linux系统,在64位Linux下把Quartus II设置成64位的方法
  10. QNX系统上用Berkeley Packet Filter直接进行原始数据的收发
  11. 如何创建计算机的桌面快捷方式,什么是快捷方式、如何创建快捷方式?
  12. 央央家政:住家育儿嫂和月嫂的工作内容明细
  13. ISA-95/B2MML教程 : 从用例到XML消息的整合实践
  14. 微信小游戏声明文件(d.ts)
  15. 移动安全工具-jadx
  16. 微博评论点赞mysql设计_微博点赞功能设计得是否合理?
  17. Give up sending metadata request since no node is available
  18. 真知灼见|客户视图与工作台:金融行业呼叫中心领域驱动设计
  19. 手机投屏电脑 - 用电脑看手机,爽歪歪!(仅限Win10,Win7/Win8不支持)
  20. 埃隆麝香下一件大事是向宽带发射4万颗卫星

热门文章

  1. 北京工业大学外网访问知网数据库方法
  2. 你沐浴后的味道,根本让人把持不住!留香24小时,比喷了大牌香水还迷人!...
  3. mac 10.13.6 升级至10.14.6再升级至12.4
  4. python:使用 PythonMagick 生成 icon 图标
  5. 2022.11.15 英语背诵
  6. Controlling the Amount of Verbatim Copying in Abstractive Summarization
  7. Level up!从流量经营到客户运营实战技术分享
  8. 百度网盘,到底限了谁的速?
  9. icloud验证失败连接服务器时出现问题,登录 iCloud 提示验证失败连接到服务器时出现问题怎么办及苹果iPhone手机安装两个微信教程...
  10. VMware的磁盘格式化