[LOJ2065] [SDOI2016]模式字符串
题目链接
洛谷:https://www.luogu.org/problemnew/show/P4075
LOJ:https://loj.ac/problem/2065
Solution
这种题看起来就很点分治啊...
我们可以发现,我们需要一个支持询问字符串相等,并且支持在一个串前面加一个串的数据结构,显然我们用哈希就行了。
那么我们直接开桶然后拿哈希维护,总复杂度\(O(Tn\log n)\)。
#include<bits/stdc++.h>
using namespace std;
template<typename T> void read(T &x) {
x=0;T ff=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') ff=-ff;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=ff;
}
void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define lf double
#define ll long long
#define pii pair<int,int >
#define vec vector<int >
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)
const int maxn = 1e6+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int bs = 29;
const int mod = 1e6+3;
ll ans;
char s[maxn];
int sz[maxn],rs[maxn],rp[maxn],rt,f[maxn],SZ,mxd,rrs[maxn],rrp[maxn];
int n,m,r[maxn],tag[maxn],head[maxn],tot,len,suf[maxn],pre[maxn],pw[maxn],vis[maxn];
struct edge{int to,nxt;}e[maxn<<1];
void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
void ins(int u,int v) {add(u,v),add(v,u);}
void prepare() {
for(len=m;len<n;len+=m)
for(int i=len+1;i<=len+m;i++) tag[i]=tag[i-len];
for(int i=1;i<=len;i++) pre[i]=(pre[i-1]*bs+tag[i])%mod;
suf[len+1]=0;for(int i=len;i;i--) suf[i]=(suf[i+1]*bs+tag[i])%mod;
reverse(suf+1,suf+len+1);
pw[0]=1;for(int i=1;i<=len;i++) pw[i]=pw[i-1]*bs%mod;
}
void get_rt(int x,int fa) {
sz[x]=1,f[x]=0;
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fa&&!vis[e[i].to]) get_rt(e[i].to,x),sz[x]+=sz[e[i].to],f[x]=max(f[x],sz[e[i].to]);
f[x]=max(f[x],SZ-sz[x]);if(f[rt]>f[x]) rt=x;
}
void calc(int x,int fa,int dep,int hs,const int &c) {
hs=(hs+1ll*r[x]*pw[dep])%mod;dep++;mxd=max(mxd,dep);
if(hs==pre[dep]) {
rrp[dep%m]++;
if(c==tag[dep%m+1]) ans+=rs[m-dep%m-1];
}
if(hs==suf[dep]) {
rrs[dep%m]++;
if(c==tag[m-dep%m]) ans+=rp[m-dep%m-1];
}
for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa&&!vis[e[i].to]) calc(e[i].to,x,dep,hs,c);
}
void dfs(int x) {
f[rt=0]=maxn;get_rt(x,0);x=rt;vis[x]=1;mxd=0;
rp[0]=rs[0]=1;int mmxd=0;
for(int i=head[x];i;i=e[i].nxt)
if(!vis[e[i].to]) {
mxd=0;calc(e[i].to,x,0,0,r[x]);mmxd=max(mmxd,mxd);
for(int j=0;j<=min(mxd,m);j++) rp[j]+=rrp[j],rs[j]+=rrs[j],rrp[j]=rrs[j]=0;
}
for(int i=0;i<=mmxd;i++) rs[i]=rp[i]=0;
for(int i=head[x];i;i=e[i].nxt)
if(!vis[e[i].to]) SZ=sz[e[i].to],dfs(e[i].to);
}
void solve() {
read(n),read(m);scanf("%s",s+1);ans=0;
for(int i=1;i<=n;i++) r[i]=s[i]-'A'+1;
for(int x,y,i=1;i<n;i++) read(x),read(y),ins(x,y);
scanf("%s",s+1);
for(int i=1;i<=m;i++) tag[i]=s[i]-'A'+1;
prepare();SZ=n;dfs(1);write(ans);
}
#define clr(x) memset(x,0,(n+3)*4)
void clear() {clr(head),clr(vis);tot=0;}
int main() {
int st=clock();
int t;read(t);while(t--) solve(),clear();
cerr << (double)(clock()-st)/1e3 << endl;
return 0;
}
[LOJ2065] [SDOI2016]模式字符串的更多相关文章
- 【BZOJ4598】[Sdoi2016]模式字符串 树分治+hash
[BZOJ4598][Sdoi2016]模式字符串 Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每 ...
- P4075 [SDOI2016]模式字符串
总结 P4075 [SDOI2016]模式字符串 题目描述 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z ...
- bzoj4598: [Sdoi2016]模式字符串
Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m 的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有 ...
- bzoj 4598: [Sdoi2016]模式字符串
题目描述 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z的大写字母. Alice希望知道,有多少对结点&l ...
- BZOJ4598 [Sdoi2016]模式字符串 【点分治 + hash】
题目 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m 的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有多少对结点< ...
- [SDOI2016]模式字符串
Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有多 ...
- BZOJ.4598.[SDOI2016]模式字符串(点分治 Hash)
LOJ BZOJ 洛谷 点分治.考虑如何计算过\(rt\)的答案. 记\(pre[i]\)表示(之前的)子树内循环匹配了\(S\)的前缀\(i\)的路径有多少,\(suf[i]\)表示(之前的)子树内 ...
- Bzoj4598: [Sdoi2016]模式字符串 点分治 哈希
国际惯例的题面:这种关于树上路径的题,我也没什么好办法,只好点分治.考虑当前分治重心为root,如何统计经过分治重心的路径的答案.我们令prf[i]表示某个点到root的路径(不含root)已经循环匹 ...
- BZOJ4598: [Sdoi2016]模式字符串(点分治 hash)
题意 题目链接 Sol 直接考虑点分治+hash匹配 设\(up[i]\)表示\(dep \% M = i\)的从下往上恰好与前\(i\)位匹配的个数 \(down\)表示\(dep \% M = i ...
随机推荐
- 干货 | 10分钟掌握branch and cut(分支剪界)算法原理附带C++求解TSP问题代码
00 前言 branch and cut其实还是和branch and bound脱离不了干系的.所以,在开始本节的学习之前,请大家还是要务必掌握branch and bound算法的原理. 01 应 ...
- javascript 之正则表达式匹配不包含特定字符串的字符
如:有如下字符串,想查出不包含min.js的字符串 ['xx.min.js','xx.js','x.js','x.min.js'] 方法一: 使用逻辑非判断, !/min\.js/.test(str ...
- bash循环得到日期目录
#!/bin/bash today=$(date "+%Y%m%d") echo 'today is :'${today} single_input="raw_data/ ...
- 初识 Python 作业及默写
1.简述变量量命名规范 2.name = input(“>>>”) name变量是什么数据类型? 3.if条件语句的基本结构? 4.用print打印出下面内容: 文能提笔安天下, 武 ...
- 升级项目版本:SpringBoot1.5.x到SpringBoot2.0.x
1.升级版本的选择 首先去spring的官网看一下最新的版本与版本之间的依赖
- 让你的shell更体贴
使用shell的时候很多,特别是拉幕式终端,使用时更加方便,同时可以利用 echo "Did you know that:" ;whatis $(ls /bin | shuf -n ...
- ICEM-四分之一带孔圆板
原视频下载地址:http://yunpan.cn/cLHCeDyzqT2Uh 访问密码 52cf
- MYSQL 什么时候用单列索引?什么使用用联合索引?
我一个表 students 表,有3个字段 ,id,name,age 我要查询 通过 name 和age,在这两个字段 是创建 联合索引?还是分别在name和age上创建 单列索引呢? 多个字段查询什 ...
- js - 总结一下条件语句优化
[笔记] // 简单的语句用三目运算符也可以的(除了需要return的) 1 == 1 ? console.log('执行了...1') : console.log(); 1 == 2 ? conso ...
- cas 3.5.3服务器搭建+spring boot集成+shiro模拟登录(不修改现有shiro认证架构)
因为现有系统外部接入需要,需要支持三方单点登录.由于系统本身已经是微服务架构,由多个业务独立的子系统组成,所以有自己的用户认证微服务(不是cas,我们基础设施已经够多了,现在能不增加就不增加).但是因 ...