传送门

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

 //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. PYTHON调用C接口(基于Ctypes)实现stein算法最大公约数的计算

    相关环境配置 mingw,选择相应的32位.64位的版本,主要用于编译动态链接库dll文件,可用vs替代,这里我选择轻量级的mingw windows64位地址:https://sourceforge ...

  2. ajax 异步 跨域上传图片

    客户端 <label for="text">名称</label> <input type="text" id="text ...

  3. P1856 [USACO5.5]矩形周长Picture

    P1856 [USACO5.5]矩形周长Picture $len$            $sum$              $num$             $flag\_l$ $flage\_ ...

  4. 解决/usr/bin/ld: cannot find -lmysqlclient错误

    类似/usr/bin/ld: cannot find -xxxx的错误有很多, 首先我们可以最简单的判断一下: 这类情况一般是由于缺乏某某库文件, 又或者可能是由于已存在的库问题版本不对造成的 一般都 ...

  5. 一篇文章教你如何用R进行数据挖掘

    一篇文章教你如何用R进行数据挖掘 引言 R是一种广泛用于数据分析和统计计算的强大语言,于上世纪90年代开始发展起来.得益于全世界众多 爱好者的无尽努力,大家继而开发出了一种基于R但优于R基本文本编辑器 ...

  6. 迁移学习——使用Tensorflow和VGG16预训模型进行预测

    使用Tensorflow和VGG16预训模型进行预测 from:https://zhuanlan.zhihu.com/p/28997549   fast.ai的入门教程中使用了kaggle: dogs ...

  7. python-多线程1

    程序\进程\线程的关系: 程序(program) 一组功能集合的静态描述,程序至少有一个进程 进程(process) 进程是系统进行资源分配和调度的,他们拥有自己独立的空间,进程至少有一个线程 线程( ...

  8. xpath normalize-sapce 函数的Java实现

    normalize-space函数实现的功能是:删除字符串前后空格,中间的空格有多个只保留一个. 1. 用Java正则表达式 public static String normalizeSpace(S ...

  9. ICE 迁移64位安装问题

    昨天手贱,在apt-get install 后有一大堆,上百个安装包not upgrade, 发现有提示apt-get autoremove,犹豫了很久后还是忍不住执行了autoremove:这个命令 ...

  10. MySQL如何计算动销率_20161025

    动销率一般反映在采购管理上,它的公式为:商品动销率=(动销品种数 /仓库总品种数)*100% . 也可以理解为销售的商品数量和仓库库存的商品数量,假如你仓库里有100个品种,在上月销售了50种,动销率 ...