传送门

这题思路太清奇了……->题解

 //minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getchar()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getchar());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
const int N=1e5+;
char str[N],s[N];
ll ans=;
int ver[N],Next[N],head[N],tot=;
int sqr,id1[N],id2[N];
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
int vis[N],rt,son[N],sz[N],size,n,m;
struct SAM{
int rt,last,tot,ch[N][],fa[N],l[N],cnt[N];
int s[N],tag[N],son[N][],le[N];
SAM(){rt=last=tot=;}
int ins(int c){
int p=last,np=++tot;last=np,le[np]=l[np]=l[p]+,cnt[np]=;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=rt;
else{
int q=ch[p][c];
if(l[q]==l[p]+) fa[np]=q;
else{
int nq=++tot;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
l[nq]=l[p]+,le[nq]=le[q];
fa[nq]=fa[q],fa[q]=fa[np]=nq;
for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
return last;
}
int a[N],c[N];
void calc(){
for(int i=;i<=tot;++i) ++c[l[i]];
for(int i=;i<=tot;++i) c[i]+=c[i-];
for(int i=tot;i;--i) a[c[l[i]]--]=i;
for(int i=tot,p;i>=;--i){
p=a[i];
cnt[fa[p]]+=cnt[p];
son[fa[p]][s[le[p]-l[fa[p]]]]=p;
}
}
void mark(int u,int fa,int now,int len){
if(!now) return;
if(len==l[now]) now=son[now][str[u]-'a'];
else if(s[le[now]-len]!=str[u]-'a') now=;
if(!now) return;
++tag[now];
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa&&!vis[v]) mark(v,u,now,len+);
}
}
inline void push(){for(int i=;i<=tot;++i) tag[a[i]]+=tag[fa[a[i]]];}
}sam1,sam2;
void findrt(int u,int fa){
sz[u]=,son[u]=;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa&&!vis[v])
findrt(v,u),sz[u]+=sz[v],cmax(son[u],sz[v]);
}
cmax(son[u],size-sz[u]);
if(!rt||son[u]<son[rt]) rt=u;
}
int num=,g[N];
void get(int u,int fa){
g[++num]=u;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa&&!vis[v]) get(v,u);
}
}
void getsum(int u,int fa){
++size;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa&&!vis[v]) getsum(v,u);
}
}
void dfs(int u,int fa,int now){
now=sam1.ch[now][str[u]-'a'];
if(!now) return;
ans+=sam1.cnt[now];
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa&&!vis[v]) dfs(v,u,now);
}
}
void work(int u,int fa,int op){
for(int i=;i<=sam1.tot;++i) sam1.tag[i]=;
for(int i=;i<=sam2.tot;++i) sam2.tag[i]=;
int to=str[fa]-'a';
if(fa) sam1.mark(u,fa,sam1.son[][to],),sam2.mark(u,fa,sam2.son[][to],);
else sam1.mark(u,fa,,),sam2.mark(u,fa,,);
sam1.push(),sam2.push();
for(int i=;i<=m;++i) ans+=1ll*op*sam1.tag[id1[i]]*sam2.tag[id2[m-i+]];
}
void solve(int u){
if(size<=sqr){
num=,get(u,);
for(int i=;i<=num;++i) dfs(g[i],,sam1.rt);
return;
}
vis[u]=,work(u,,);
for(int i=head[u];i;i=Next[i])
if(!vis[ver[i]]) work(ver[i],u,-);
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(vis[v]) continue;
size=,getsum(v,u);
rt=,findrt(v,u);
solve(rt);
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=,u,v;i<n;++i)
u=read(),v=read(),add(u,v),add(v,u);
scanf("%s",str+),scanf("%s",s+);
for(int i=;i<=m;++i) sam1.s[i]=s[i]-'a',id1[i]=sam1.ins(s[i]-'a');
reverse(s+,s++m);
for(int i=;i<=m;++i) sam2.s[i]=s[i]-'a',id2[i]=sam2.ins(s[i]-'a');
sam1.calc(),sam2.calc();
rt=,son[]=n+,size=n,sqr=sqrt(n);
findrt(,),solve(rt);
printf("%lld\n",ans);
return ;
}

洛谷P4218 [CTSC2010]珠宝商(后缀自动机+点分治)的更多相关文章

  1. 洛谷P4248 [AHOI2013]差异(后缀自动机求lcp之和)

    题目见此 题解:首先所有后缀都在最后一个np节点,然后他们都是从1号点出发沿一些字符边到达这个点的,所以下文称1号点为根节点,我们思考一下什么时候会产生lcp,显然是当他们从根节点开始一直跳相同节点的 ...

  2. P4218 [CTSC2010]珠宝商

    P4218 [CTSC2010]珠宝商 神题... 可以想到点分治,细节不写了... (学了个新姿势,sam可以在前面加字符 但是一次点分治只能做到\(O(m)\),考虑\(\sqrt n\)点分治, ...

  3. 洛谷-P5357-【模板】AC自动机(二次加强版)

    题目传送门 -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题 sol:AC自动机,还是要解决跳fail边产生的重复访问,但 ...

  4. [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)

    题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...

  5. 洛谷P1393 动态逆序对(CDQ分治)

    传送门 题解 听别人说这是洛谷用户的双倍经验啊……然而根本没有感觉到……因为另外的那题我是用树状数组套主席树做的……而且莫名其妙感觉那种方法思路更清晰(虽然码量稍稍大了那么一点点)……感谢Candy大 ...

  6. Bzoj2152/洛谷P2634 聪聪可可(点分治)

    题面 Bzoj 洛谷 题解 点分治套路走一波,考虑\(calc\)函数怎么写,存一下每条路径在\(\%3\)意义下的路径总数,假设为\(tot[i]\)即\(\equiv i(mod\ 3)\),这时 ...

  7. 洛谷 P6199 - [EER1]河童重工(点分治+虚树)

    洛谷题面传送门 神仙题. 首先看到这样两棵树的题目,我们肯定会往动态树分治的方向考虑.考虑每次找出 \(T_2\) 的重心进行点分治.然后考虑跨过分治中心的点对之间的连边情况.由于连边边权与两棵树都有 ...

  8. 洛谷P3966 [TJOI2013]单词(AC自动机)

    题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出格式 输入格式: 第一行一个整数N,表 ...

  9. 洛谷P2444 病毒【AC自动机】

    题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否 ...

随机推荐

  1. Cmder配置

    中文乱码和重叠 当我们使用ls命令查看文件目录时,发现,中文被显示成了一些奇怪的乱码,将以下几行代码配置在cmder/config/user-aliases下即可解决问题: l=ls --show-c ...

  2. http://blog.csdn.net/renfufei/article/details/37725057/

    版权声明:本文为博主原创文章,未经博主允许不得转载. 原创:http://blog.csdn.net/renfufei/article/details/37725057/ 说明: 首先,你需要注册一个 ...

  3. HDU2825 Wireless Password —— AC自动机 + 状压DP

    题目链接:https://vjudge.net/problem/HDU-2825 Wireless Password Time Limit: 2000/1000 MS (Java/Others)    ...

  4. SpringMVC的API和Spring的官方说明文档的地址。

    SpringMVC的API和Spring的官方说明文档的地址. 1.SpringMVC的API的URL: http://docs.spring.io/spring/docs/current/javad ...

  5. matlab之sum()函数

    sum(A,1):对矩阵A按照列求和: sum(A,2):对矩阵A按照行求和: 默认情况下,是按照列求和的. 举例: A=[1 2 3;1 2 3] sum(A,1)的结果: ans = 2 4 6 ...

  6. PHP按照比例随机

    有这样的需求,在打开链接的时候,随机(按照项目的某个属性的比例随机)跳转到指定的几个项目的某一个项目页面 比如项目A:80  项目B:20 那么跳转到项目A 的比例为80%,项目B的比例为20% 那么 ...

  7. 手机移动端网站开发流程HTML5

    手机移动端网站开发流程HTML5 最近一直在研究移动手机网站的开发,发现做手机网站没有想象中的那么难.为什么会这么说呢?我们试想下:我们连传统的PC网站都会做,难道连一个小小的手机网站难道都搞不定吗? ...

  8. 分享知识-快乐自己:初始 Struts2 (基本概念)及 搭建第一个Demo

    1):struts2 的基本概念: 1-1):Struts2 是什么? 1.Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2 ...

  9. workerman介绍

    WorkerMan的特性 1.纯PHP开发 使用WorkerMan开发的应用程序不依赖php-fpm.apache.nginx这些容器就可以独立运行. 这使得PHP开发者开发.部署.调试应用程序非常方 ...

  10. L98

    If there's one thing to be taught, it's dreams are made to be caught.唯有一事值得谨记,有梦想就要奋力追逐Capital punis ...