[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 ...
随机推荐
- 51Nod 1769 Clarke and math2
51Nod 1769 Clarke and math2 http://www.51nod.com/Challenge/Problem.html#!#problemId=1769 要算的是\(G=F*I ...
- linux常用命名汇总:自用,持续更新
1.查看磁盘空间大小 df -hl 查看磁盘剩余空间 df -h 查看每个根路径的分区大小 du -sh [目录名] 返回该目录的大小 du -sm [文件夹] 返回该文件夹总M数 du -h [目录 ...
- [C++] namespace命名空间和using用法
命名空间namespace:指标识符的各种可见范围. C++标准程序库中的所有标识符都被定义在一个std的namespace,这就是程序开始添加 using namespace std; 的原因. 很 ...
- 第07组 Alpha冲刺(5/6)
队名:摇光 队长:杨明哲 组长博客:求戳 作业博客:求再戳 队长:杨明哲 过去两天完成了哪些任务 文字/口头描述:依然在完善网页编辑器的后端. 展示GitHub当日代码/文档签入记录:(组内共用,已询 ...
- RUN vs CMD vs ENTRYPOINT
参考:https://www.ibm.com/developerworks/community/blogs/132cfa78-44b0-4376-85d0-d3096cd30d3f/entry/RUN ...
- python 图片格式转换png转jpg,如何利用python给图片添加半透明水印
from PIL import Imageim = Image.open(r'd:\test2.png')r, g, b, a = im.split()im = Image.merge("R ...
- protobuf使用
一.protobuf环境搭建 Github 地址: https://github.com/protocolbuffers/protobuf 然后进入下载页 https://github.com/pro ...
- Linux下emacs如何安装
ftp://ftp.gnu.org/gnu/emacs/ 下载对应版本编译安装 cd 自己想安装的目录 sudo wget ftp://ftp.gnu.org/gnu/emacs/emacs-24.4 ...
- matlab学习笔记10 一般运算符
一起来学matlab-matlab学习笔记10 10_1一般运算符 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张 ...
- 元数据Meta
元数据,指的是“除了字段外的所有内容”,例如排序方式.数据库表名.人类可读的单数或者复数名等等.所有的这些都是非必须的,甚至元数据本身对模型也是非必须的. 在模型中增加元数据,需要在模型类中添加一个子 ...