ref不是太懂

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef unsigned long long ull;
int T, n, m, hea[1000005], cnt, uu, vv, rnd[1000005], rot, siz[1000005];
int tot, sf[1000005], sg[1000005], ff[1000005], gg[1000005];
ull bse[1000005], hs1[1000005], hs2[1000005], ans;
char ss[1000005], tt[1000005];
bool vis[1000005];
struct Edge{
int too, nxt;
}edge[2000005];
void rn(int &x){
char ch=getchar();
x = 0;
while(ch<'0' || ch>'9') ch = getchar();
while(ch>='0' && ch<='9'){
x = x * 10 + ch - '0';
ch = getchar();
}
}
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
void getRoot(int x, int f){
rnd[x] = 0;
siz[x] = 1;
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(!vis[t] && t!=f){
getRoot(t, x);
siz[x] += siz[t];
rnd[x] = max(rnd[x], siz[t]);
}
}
rnd[x] = max(rnd[x], tot-siz[x]);
if(rnd[x]<rnd[rot]) rot = x;
}
int dfs(int x, int f, int d, ull hx){
siz[x] = 1;
hx = hx * 131 + ss[x];
if(hs1[d]==hx){
ff[(d-1)%m+1]++;
ans += sg[m-(d-1)%m];
}
if(hs2[d]==hx){
gg[(d-1)%m+1]++;
ans += sf[m-(d-1)%m];
}
int tmp=1;
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(!vis[t] && t!=f){
siz[x] += siz[t];
tmp = max(tmp, dfs(t, x, d+1, hx)+1);
}
}
return tmp;
}
void work(int x){
vis[x] = true;
sf[1] = sg[1] = 1;
int tmp=0;
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(!vis[t]){
int k=min(m, dfs(t, x, 2, ss[x])+1);
tmp = max(tmp, k);
for(int j=1; j<=k; j++){
sf[j] += ff[j];
sg[j] += gg[j];
ff[j] = gg[j] = 0;
}
}
}
for(int i=1; i<=tmp; i++)
sf[i] = sg[i] = 0;
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(!vis[t]){
rot = 0;
tot = siz[t];
getRoot(t, x);
work(rot);
}
}
}
int main(){
cin>>T;
while(T--){
rn(n); rn(m);
scanf("%s", ss+1);
memset(hea, 0, sizeof(int)*(n+1));
memset(vis, 0, sizeof(bool)*(n+1));
cnt = ans = rot = 0;
tot = n;
for(int i=1; i<n; i++){
rn(uu); rn(vv);
add_edge(uu, vv);
add_edge(vv, uu);
}
scanf("%s", tt+1);
bse[0] = 1;
for(int i=1; i<=n; i++){
bse[i] = bse[i-1] * 131;
hs1[i] = hs1[i-1] + tt[(i-1)%m+1] * bse[i-1];
hs2[i] = hs2[i-1] + tt[m-(i-1)%m] * bse[i-1];
}
rnd[0] = 0x3f3f3f3f;
getRoot(1, 0);
work(rot);
printf("%llu\n", ans);
}
return 0;
}

loj2065 「SDOI2016」模式字符串的更多相关文章

  1. 题解 loj2065 「SDOI2016」模式字符串

    点分治. 考虑经过当前分治中心\(u\)的点对数量. 这种数点对数的问题,有一个套路.我们可以依次考虑\(u\)的每个儿子,看用当前的儿子,能和之前已经考虑过的所有儿子,组成多少点对.这样所有合法的点 ...

  2. 【LOJ】#2065. 「SDOI2016」模式字符串

    题解 按秩合并怎么清数组对我来说真是世纪性难题 我们很熟练地想到点分,如果我们认为某个点到重心是正着读的,由于它的深度固定,它的串也是固定的,我们只要预处理出所有长度正着重复的串,反着重复的串,和它们 ...

  3. liberOJ #2033. 「SDOI2016」生成魔咒 后缀数组

    #2033. 「SDOI2016」生成魔咒     题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 11.2 22 拼凑起来形成一个魔咒串 [1,2] [1, 2] ...

  4. 「SDOI2016」储能表(数位dp)

    「SDOI2016」储能表(数位dp) 神仙数位 \(dp\) 系列 可能我做题做得少 \(QAQ\) \(f[i][0/1][0/1][0/1]\) 表示第 \(i\) 位 \(n\) 是否到达上界 ...

  5. [LOJ 2070] 「SDOI2016」平凡的骰子

    [LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...

  6. 「SDOI2016」数字配对

    「SDOI2016」数字配对 题目大意 传送门 题解 \(a_i\) 是 \(a_j\) 的倍数,且 \(\frac{a_i}{a_j}\) 是一个质数,则将 \(a_i,a_j\) 质因数分解后,其 ...

  7. 「SDOI2016」征途 题解

    「SDOI2016」征途 先浅浅复制一个方差 显然dp,可以搞一个 \(dp[i][j]\)为前i段路程j天到达的最小方差 开始暴力转移 \(dp[i][j]=min(dp[k][j-1]+?)(j- ...

  8. loj2424 「NOIP2015」子串[字符串DP]

    给定字符串 A,B,要求从 A 中取出互不重叠的 k 个非空子串,按照出现顺序拼起来后等于 B.求方案数.n ≤ 1000,m ≤ 200. 主要是状态的转移.先设计出$f_{i,j,k}$表长度$B ...

  9. 【LOJ】#2070. 「SDOI2016」平凡的骰子

    题解 用了一堆迷之复杂的结论结果迷之好写的计算几何???? 好吧,要写立体几何了 如果有名词不懂自己搜吧 首先我们求重心,我们可以求带权重心,也就是x坐标的话是所有分割的小四面体的x坐标 * 四面体体 ...

随机推荐

  1. windows下 php集成环境如何通过cmd执行命令

    ---恢复内容开始--- php学习过程中 Windows环境下的php集成程序很多 这样方便了学习 但是在熟悉命令使用方面可以说是十分不便 本文将从两个方便 向大家介绍如何快速通过cmd命令实现命令 ...

  2. vc++ 6.0编译后生成的文件

    程序在编译后,在目标路径下会生成多个文件    Debug文件夹(*.exe,*.ilk,*.obj,*.pch,*.pdb,*.idb,*,pdb),*.cpp,*.dsp,*.ncb,*.plg  ...

  3. C# 获取当前文件、文件夹的路径及操作环境变量

    一.获取当前文件的路径 1.   System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName      获取模块的完整路径,包 ...

  4. JS浏览器获取宽高

    screen.availHeight is the height the browser's window can have if it is maximized. (including all th ...

  5. nrm—源管理工具

    全局安装 npm install -g nrm 查看可选源 nrm ls 其中,带*的是当前使用的源,上面的输出表明当前源是hiknpm 切换源 nrm use taobao 新增源 nrm add ...

  6. linux 命令——54 ping(转)

    Linux系统的ping 命令是常用的网络命令,它通常用来测试与目标主机的连通性,我们经常会说“ping一下某机器,看是不是开着”.不能打开网页时会说“你先ping网关地 址192.168.1.1试试 ...

  7. NET_Framework_4.0installer.rar

    部署提示: 1.首先下载有关的安装程序 NET_Framework_4.0installer.rar 这是我整理好的四个软件(大致一共10MB),分别如下 WindowsInstaller-KB893 ...

  8. Java中ArrayList的对象引用问题

    前言事件起因是由于同事使用ArrayList的带参构造方法进行ArrayList对象复制,修改新的ArrayList对象中的元素(对象)的成员变量时也会修改原ArrayList中的元素(对象)的成员变 ...

  9. linux slab学习

    https://blog.csdn.net/bullbat/article/details/7194794 https://blog.csdn.net/qq_26626709/article/deta ...

  10. 【DBA-Oracle】更改Oracle数据字符集_转为常用的ZHS16GBK

    A.oracle server 端 字符集查询  select userenv('language') from dual 其中NLS_CHARACTERSET 为server端字符集 NLS_LAN ...