题意

题目链接

Sol

直接考虑点分治+hash匹配

设\(up[i]\)表示\(dep \% M = i\)的从下往上恰好与前\(i\)位匹配的个数

\(down\)表示\(dep \% M = i\)的从上往下恰好与后\(i\)位匹配的个数

暴力转移即可

复杂度:\(O(nlog^2n)??\)

代码写起来有一车边界

#include<bits/stdc++.h>
#define ull unsigned long long
#define LL long long
#define int long long
#define siz(v) ((int)v.size())
using namespace std;
const int MAXN = 1e6 + 10, INF = 1e10 + 10;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, M, Root, siz[MAXN], mx[MAXN], Siz, dep[MAXN], up[MAXN], down[MAXN], su[MAXN], sd[MAXN];
LL ans;
bool det[MAXN];
char a[MAXN], b[MAXN];
vector<int> v[MAXN];
ull hs[MAXN], hp[MAXN], po[MAXN], base = 1331;
map<ull, bool> mp;
void FindRoot(int x, int fa) {
siz[x] = 1; mx[x] = 0;
for(int i = 0; i < siz(v[x]); i++) {
int to = v[x][i];
if(to == fa || det[to]) continue;
FindRoot(to, x);
siz[x] += siz[to]; mx[x] = max(mx[x], siz[to]);
}
mx[x] = max(mx[x], Siz - siz[x]);
if(mx[x] < mx[Root]) Root = x;
}
int dfs(int x, int fa, ull now) {
siz[x] = 1;
dep[x] = dep[fa] + 1;
now = now * base + a[x];
if(hp[dep[x]] == now) up[(dep[x] - 1) % M + 1]++, ans += sd[M - (dep[x] - 1) % M];
if(hs[dep[x]] == now) down[(dep[x] - 1) % M + 1]++, ans += su[M - (dep[x] - 1) % M];
// printf("%d %d\n", x, ans);
int td =1;
for(int i = 0; i < siz(v[x]); i++) {
int to = v[x][i];
if(to == fa || det[to]) continue;
td = max(td, dfs(to, x, now) + 1);
siz[x] += siz[to];
}
return td;
}
void work(int x) {
int tk = 0, tmp = 0;
det[x] = 1; dep[x] = 1; su[1] = sd[1] = 1;//tag;
for(int i = 0; i < siz(v[x]); i++) {
int to = v[x][i];
if(det[to]) continue;
tk = min(M, dfs(to, x, a[x]) + 1), tmp = max(tmp, tk);
for(int j = 1; j <= tk; j++) su[j] += up[j], sd[j] += down[j], up[j] = down[j] = 0;
}
for(int i = 1; i <= tmp; i++) su[i] = sd[i] = 0;
for(int i = 0; i < siz(v[x]); i++) {
int to = v[x][i];
if(to == x || det[to]) continue;
Siz = siz[to]; Root = 0; FindRoot(to, x);
work(Root);
}
}
void init() {
for(int i = 1; i <= N; i++) v[i].clear();
memset(det, 0, sizeof(det));
memset(siz, 0, sizeof(siz));
memset(mx, 0, sizeof(mx));
ans = 0;
}
void solve() { N = read(); M = read();
init();
scanf("%s", a + 1);
for(int i = 1; i <= N - 1; i++) {
int x = read(), y = read();
v[x].push_back(y); v[y].push_back(x);
}
for(int i = 1; i <= N; i++) reverse(v[i].begin(), v[i].end());
scanf("%s", b + 1); po[0] = 1;
for(int i = 1; i <= N; i++) {
hp[i] = hp[i - 1] + b[(i - 1) % M + 1] * po[i - 1];
hs[i] = hs[i - 1] + b[M - (i - 1) % M] * po[i - 1];
po[i] = base * po[i - 1];
}
Siz = N; mx[0] = INF; Root = 0; FindRoot(1, 0);
work(1);
printf("%d\n", ans);
}
signed main() {
freopen("a.in", "r", stdin);
for(int T = read(); T; T--, solve());
return 0;
}

BZOJ4598: [Sdoi2016]模式字符串(点分治 hash)的更多相关文章

  1. 【BZOJ4598】[Sdoi2016]模式字符串 树分治+hash

    [BZOJ4598][Sdoi2016]模式字符串 Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每 ...

  2. BZOJ.4598.[SDOI2016]模式字符串(点分治 Hash)

    LOJ BZOJ 洛谷 点分治.考虑如何计算过\(rt\)的答案. 记\(pre[i]\)表示(之前的)子树内循环匹配了\(S\)的前缀\(i\)的路径有多少,\(suf[i]\)表示(之前的)子树内 ...

  3. Bzoj4598: [Sdoi2016]模式字符串 点分治 哈希

    国际惯例的题面:这种关于树上路径的题,我也没什么好办法,只好点分治.考虑当前分治重心为root,如何统计经过分治重心的路径的答案.我们令prf[i]表示某个点到root的路径(不含root)已经循环匹 ...

  4. BZOJ4598 [Sdoi2016]模式字符串 【点分治 + hash】

    题目 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m 的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有多少对结点< ...

  5. bzoj4598: [Sdoi2016]模式字符串

    Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m 的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有 ...

  6. P4075 [SDOI2016]模式字符串

    总结 P4075 [SDOI2016]模式字符串 题目描述 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z ...

  7. [SDOI2016] 模式字符串 (BZOJ4598 & VIJOS1995)

    首先直接点分+hash就可以做,每个点用hash判断是否为S重复若干次后的前缀或后缀,每个子树与之前的结果O(m)暴力合并.在子树大小<m时停止分治,则总复杂度为O(nlog(n/m)). 问题 ...

  8. bzoj 4598: [Sdoi2016]模式字符串

    题目描述 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z的大写字母. Alice希望知道,有多少对结点&l ...

  9. [SDOI2016]模式字符串

    Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有多 ...

随机推荐

  1. Windows Server 2012 R2 部署DC及主辅DC

    背景信息: 资源组:hlmdcn DC1:windows Server 2012 R2 Datacenter, A2, hlmdc1, 10.8.0.4DC2:windows Server 2012 ...

  2. SpringMvc redirect

    SpringMVC redirect 核心 首先网上百度到的资源基本已经够用, 留作记录. SpringMVC-redirect重定向跳转传值 虽然这哥们也是转的, 但又没有留源地址. 因此 ... ...

  3. java连接hbase时出现....is accessible from more than one module:

    今天在用java程序连接hbase时,出现错误,The package org.apache.hadoop.hbase is accessible from more than one module: ...

  4. 关于nginx的一个错误操作记录

    今天在弄前后端同步的测试的时候,前端用Nginx代理访问后端接口,由于启动了多次nginx软件,没有将前几次启动的nginx进程关闭,导致在访问后端接口的request被挂起,过了半天也没有结果返回, ...

  5. word前页与后页页码断开

    方法一:以Word2013为例:1. 光标移动到目录页的最后一行,从“页面布局”选项卡“分隔符”中选择“下一页”类型的“分节符”,删除多余的行.分页符等(图1): 2. 双击正文任意一页的页眉/页脚区 ...

  6. 基础概念——理解IP地址和域名

    从程序员角度,可以把因特网看做是世界范围内的主机集合: 1)主机集合被映射为一组32位的IP地址. 2)这个IP地址被映射为一组称为因特网域名的标识符. 3)因特网主机上的进程能够通过连接和任何其他因 ...

  7. 基于Anaconda 安装 geatpy 和 tensorflow

    装了好久的第三方包终于成功了,暴风哭泣!!!总结一下 分两部分说: 一. 首先是在本地电脑windows系统下装: 首先安利一下这个包括各种 Genetic and Evolutionary Algo ...

  8. vue遇见better-scroll

    better-scroll better-scroll 是一款重点解决移动端(现已支持 PC 端)各种滚动场景需求的插件.它的核心是借鉴的 iscroll 的实现,它的 API 设计基本兼容 iscr ...

  9. codeblocks中文编码问题

    其实这是老调重弹的问题了,在windows下面出现中文乱码大多都是编码格式的问题不一致的问题,最简单的就是uft-8和gbk冲突的问题.如果一个文件本来是以utf-8存的,但是以gbk打开,当然会出现 ...

  10. WPF的Label默认的padding不为0

    1.如图: 要求让“Tools” 左对齐,代码中已设置:HorizontalContentAlignment="Left" <Label Foreground="W ...