#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 800005
#define maxm 1600005
#define maxl 1600005
#define ll long long
using namespace std;
int n,cnt,m,last,root,tot,val[maxl],now[maxn],son[maxl],prep[maxl],ri[maxm],fa[maxm],dist[maxm],tmp[maxm];
ll sum[maxm],ans;
char st[maxn*];
struct Tsegment{
int son[maxm][];
void prepare(){tot=last=root=,memset(ri,,sizeof(ri)),memset(son,,sizeof(son)),memset(dist,,sizeof(dist));}
int newnode(int x){
dist[++tot]=x; return tot;
}
int add(int x,int p){
int q=son[p][x];
if (q==){
int np=newnode(dist[p]+); last=np; ri[np]=;
for (;p&&!son[p][x];p=fa[p]) son[p][x]=np;
if (p==) fa[np]=root;
else{
int q=son[p][x];
if (dist[p]+==dist[q]) fa[np]=q;
else{
int nq=newnode(dist[p]+);
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q],fa[q]=fa[np]=nq;
for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;
}
}
}else{
if (dist[p]+==dist[q]) last=q,ri[q]++;
else{
int nq=newnode(dist[p]+); last=nq; ri[nq]=;
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q],fa[q]=nq;
for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;
}
}
return last;
}
void Tsort(){
memset(sum,,sizeof(sum));
for (int i=;i<=tot;i++) sum[dist[i]]++;
for (int i=;i<=n;i++) sum[i]+=sum[i-];
for (int i=;i<=tot;i++) tmp[sum[dist[i]]--]=i;
memset(sum,,sizeof(sum));
for (int x,i=tot;i>=;i--){
x=tmp[i];
if (fa[x]) ri[fa[x]]+=ri[x];
}
ri[root]=,dist[root]=dist[]=;
for (int x,i=;i<=tot;i++){
x=tmp[i];
sum[x]=ri[x]*(dist[x]-dist[fa[x]]);
if (fa[x]) sum[x]+=sum[fa[x]];
}
sum[root]=;
}
void work(){
int len=; last=root; ans=;
for (int x,i=;i<=m;i++){
x=st[i]-'a';
if (son[last][x]) len++,last=son[last][x];
else{
for (;last&&!son[last][x];last=fa[last]);
if (last==) last=root,len=;
else{
len=dist[last]+,last=son[last][x];
}
}
if (last!=root&&last){
ans+=(sum[fa[last]]+(len-dist[fa[last]])*ri[last]);
}
}
printf("%lld\n",ans);
}
}SAM;
struct Graph{
void add(int x,int y,int z){
cnt++,prep[cnt]=now[x],now[x]=cnt,son[cnt]=y,val[cnt]=z;
}
void dfs(int x,int goal){
for (int i=now[x],so=son[i];i;i=prep[i],so=son[i]){
int p=SAM.add(val[i],goal);
dfs(so,p);
}
}
}G;
int main(){
scanf("%d",&n);
cnt=ans=,memset(now,,sizeof(now));
for (int i=,u,v;i<=n;i++){
scanf("%d%s",&u,st+);
G.add(u,i,st[]-'a');
}
SAM.prepare();
G.dfs(,);
SAM.Tsort();
scanf("%s",st+),m=strlen(st+);
SAM.work();
return ;
}

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3756

题目大意:

在神秘的东方有一棵奇葩的树,它有一个固定的根节点(编号为1)。树的每条边上都是一个字符,字符为a,b,c中的一个,你可以从树上的任意一个点出发,然后沿着远离根的边往下行走,在任意一个节点停止,将你经过的边的字符依次写下来,就能得到一个字符串,例如:
 
在这棵树中我们能够得到的字符串是:
c, cb, ca, a, b, a
现在pty得到了一棵树和一个字符串S。如果S的一个子串[l,r]和树上某条路径所得到的字符串完全相同,则我们称这个子串和该路径匹配。现在pty想知道,S的所有子串和树上的所有路径的匹配总数是多少?
做法:看到此题,我们可以发现,先将题目中给定的trie树建立一个广义后缀自动机,预处理出每个点的right值,dist值,sum值,前两个都是后缀自动机自带的,不用说了,sum表示parent树中该点到根节点的路径上所有的字符串的数目(能使后面的复杂度降至O(n)级别的),然后用输入的字符串在SAM上匹配即可,与普通匹配相似,但是统计答案不一样,ans+=(sum【fa【x】】+right【x】*(len-dist【x】)),x表示走到的点,len表示匹配的长度,为什么呢?除了要将走到的状态带来的答案外,parent树中这个点的祖先节点都能完全匹配到,所以要加上sum【fa【x】】。记得sum和ans要开long long 。
做法:广义后缀自动机。

bzoj3756: Pty的字符串的更多相关文章

  1. 【BZOJ3756】Pty的字符串(广义后缀自动机)

    题意: 思路:论文题 建立Trie树的后缀自动机需要换这个长的板子 #include<bits/stdc++.h> using namespace std; typedef long lo ...

  2. Pty的字符串(string)

    题目描述 在神秘的东方有一棵奇葩的树,它有一个固定的根节点(编号为1).树的每条边上都是一个字符,字符为a,b,c中的一个,你可以从树上的任意一个点出发,然后沿着远离根的边往下行走,在任意一个节点停止 ...

  3. [JZOJ3402] 【GDOI2014模拟】Pty的字符串

    题目 给你一棵每条边从父亲指向儿子的树,每条边上面有一个字母. 从树上的任意一点出发,走出的路径就是对应一个子串. (这不是\(Trie\),因为每个父亲可能会连出字母相同的边) 再给你一个字符串\( ...

  4. [BZOJ 2894]世界线

    传送门 \(\color{green}{solution}\) 在开这道题之前建议先看看3756:pty的字符串,然后你会发现这题就很zz了. 当然,作为一名合格的博主,我还是应该写点什么的 首先,我 ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. (从终端看linux-1)linux tty pty pts 概念 区别

    基本概念: 1> tty(终端设备的统称):tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息的东西,后来这东 ...

  7. Linux中tty、pty、pts的概念区别

    转自Linux中tty.pty.pts的概念区别 基本概念: 1> tty(终端设备的统称): tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过 ...

  8. Linux中tty、pty、pts的概念区别 转载

    基本概念: > tty(终端设备的统称): tty一词源于Teletypes,或teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息的东西,后来这东西 ...

  9. 字符串的朴素模式和KMP模式匹配

    先复习一下字符串指针: #include <iostream> #include <string.h> using namespace std; int main() { ch ...

随机推荐

  1. NOI2018准备Day5

    3个半小时,连看题解带超过了一道二分题.

  2. HTTP错误代码

    服务器错误代码大全 ·400 - 错误的请求. ·401 - 访问被拒绝.IIS 定义了许多不同的 401 错误,它们指明更为具体的错误原因.这些具体的错误代码在浏览器中显示,但不在 IIS 日志中显 ...

  3. TinyFrame开篇:基于CodeFirst的ORM

    前言 做项目的这段时间,由于比较忙,一直没有机会闲下来思考.正好趁目前手头活儿轻松点,就花了一两天时间搭建了一个比较简单的框架,名称暂时就叫做:TinyFrame吧.顾名思义,就是微框架的意思.虽然这 ...

  4. CUDA2.1-原理之索引与warp

    本小节来自<大规模并行处理器编程实战>第四节,该书是很好的从内部原理结构上来讲述了CUDA的,对于理解CUDA很有帮助,借以博客的形式去繁取间,肯定会加入自己个人理解,所以有错误之处还望指 ...

  5. 给Asp.Net MVC及WebApi添加路由优先级

    一.为什么需要路由优先级 大家都知道我们在Asp.Net MVC项目或WebApi项目中注册路由是没有优先级的,当项目比较大.或有多个区域.或多个Web项目.或采用插件式框架开发时,我们的路由注册很可 ...

  6. hystrix-turbine 监控的使用

    1.   概述 Demo地址:http://git.oschina.net/zhou666/spring-cloud-7simple/tree/master/cloud-hystrix-turbine ...

  7. DEV winform treelist设置背景图像

    treelist是一个复杂的控件,包括选中行,奇偶行等均可以单独设置显示效果,空白区域上背景图像的代码如下: private void treeList1_CustomDrawEmptyArea(ob ...

  8. HDInsight - 1,简介

    最近工作需要,要看HDInsight部分,这里要做笔记.自然是官网资料最权威,所以内容都从这里搬过来:https://azure.microsoft.com/en-us/documentation/a ...

  9. 最小/大费用最大流模板(codevs1914)

    void addedge(int fr,int to,int cap,int cos){ sid[cnt].fr=fr;sid[cnt].des=to;sid[cnt].cap=cap;sid[cnt ...

  10. 通过android 客户端上传图片到服务器

    昨天,(在我的上一篇博客中)写了通过浏览器上传图片到服务器(php),今天将这个功能付诸实践.(还完善了服务端的代码) 不试不知道,原来通过android 向服务端发送图片还真是挺麻烦的一件事. 上传 ...