题目链接

洛谷: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]模式字符串的更多相关文章

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

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

  2. P4075 [SDOI2016]模式字符串

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

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

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

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

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

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

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

  6. [SDOI2016]模式字符串

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

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

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

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

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

  9. BZOJ4598: [Sdoi2016]模式字符串(点分治 hash)

    题意 题目链接 Sol 直接考虑点分治+hash匹配 设\(up[i]\)表示\(dep \% M = i\)的从下往上恰好与前\(i\)位匹配的个数 \(down\)表示\(dep \% M = i ...

随机推荐

  1. 51Nod 1769 Clarke and math2

    51Nod 1769 Clarke and math2 http://www.51nod.com/Challenge/Problem.html#!#problemId=1769 要算的是\(G=F*I ...

  2. linux常用命名汇总:自用,持续更新

    1.查看磁盘空间大小 df -hl 查看磁盘剩余空间 df -h 查看每个根路径的分区大小 du -sh [目录名] 返回该目录的大小 du -sm [文件夹] 返回该文件夹总M数 du -h [目录 ...

  3. [C++] namespace命名空间和using用法

    命名空间namespace:指标识符的各种可见范围. C++标准程序库中的所有标识符都被定义在一个std的namespace,这就是程序开始添加 using namespace std; 的原因. 很 ...

  4. 第07组 Alpha冲刺(5/6)

    队名:摇光 队长:杨明哲 组长博客:求戳 作业博客:求再戳 队长:杨明哲 过去两天完成了哪些任务 文字/口头描述:依然在完善网页编辑器的后端. 展示GitHub当日代码/文档签入记录:(组内共用,已询 ...

  5. RUN vs CMD vs ENTRYPOINT

    参考:https://www.ibm.com/developerworks/community/blogs/132cfa78-44b0-4376-85d0-d3096cd30d3f/entry/RUN ...

  6. python 图片格式转换png转jpg,如何利用python给图片添加半透明水印

    from PIL import Imageim = Image.open(r'd:\test2.png')r, g, b, a = im.split()im = Image.merge("R ...

  7. protobuf使用

    一.protobuf环境搭建 Github 地址: https://github.com/protocolbuffers/protobuf 然后进入下载页 https://github.com/pro ...

  8. Linux下emacs如何安装

    ftp://ftp.gnu.org/gnu/emacs/ 下载对应版本编译安装 cd 自己想安装的目录 sudo wget ftp://ftp.gnu.org/gnu/emacs/emacs-24.4 ...

  9. matlab学习笔记10 一般运算符

    一起来学matlab-matlab学习笔记10 10_1一般运算符 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张 ...

  10. 元数据Meta

    元数据,指的是“除了字段外的所有内容”,例如排序方式.数据库表名.人类可读的单数或者复数名等等.所有的这些都是非必须的,甚至元数据本身对模型也是非必须的. 在模型中增加元数据,需要在模型类中添加一个子 ...