bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机)

bzoj Luogu

题解时间

给你个无根trie树(你管这叫trie树?),问你选取一条有向路径能形成多少种不同字符串。

太阳花田的结构比较特殊,只与一个空地相邻的空地数量不超过20个。->只有不超过20个叶子。

纯粹看你读题的,你要是读错了这句话的含义你就白给。

如何保证完整枚举这棵树上所有可能的字符串呢?

我们以某个点为根建广义SAM,很明显每一个点都只有向根方向延展出的字符串没有被记入了SAM中。

而对于一个叶子节点,只有以它为根建SAM时,以它为起点延展出的字符串才会被记录。

而对于一个非叶子节点,很明显一定有两个叶子节点在它的不同方向。

所以只需要对于每个叶子节点为根建广义SAM放在一起进行统计即可。

本质不同字符串个数为 $ \Sigma len[x]-len[pre[x]] $ 。

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
namespace RKK
{
const int N=200011,L=30;
struct yuuka{int to,ne;}e[N];int he[N],ecnt,ind[N];
void addline(int f,int t)
{
    e[++ecnt].to=t;
    e[ecnt].ne=he[f];
    he[f]=ecnt;
    ind[t]++;
}
int n,str[N];
lint ans;
struct remilia{int tranc[10],len,pre;};
struct sakuya
{
    remilia s[N*20];
    int fin,size;
    sakuya(){fin=size=1;}
    void ins(int ch)
    {
        int npx,npy,lpx,lpy;
        if(s[fin].tranc[ch])
        {
            lpy=s[fin].tranc[ch],lpx=fin;
            if(s[lpy].len==s[lpx].len+1) fin=lpy;
            else
            {
                npy=++size;
                s[npy]=s[lpy];
                s[npy].len=s[lpx].len+1;
                s[lpy].pre=npy;
                while(s[lpx].tranc[ch]==lpy)
                {
                    s[lpx].tranc[ch]=npy;
                    lpx=s[lpx].pre;
                }
                fin=npy;
            }
            return;
        }
        npx=++size;
        s[npx].len=s[fin].len+1;
        for(lpx=fin;lpx&&!s[lpx].tranc[ch];lpx=s[lpx].pre) s[lpx].tranc[ch]=npx;
        if(!lpx) s[npx].pre=1;
        else
        {
            lpy=s[lpx].tranc[ch];
            if(s[lpy].len==s[lpx].len+1) s[npx].pre=lpy;
            else
            {
                npy=++size;
                s[npy]=s[lpy];
                s[npy].len=s[lpx].len+1;
                s[npx].pre=s[lpy].pre=npy;
                while(s[lpx].tranc[ch]==lpy)
                {
                    s[lpx].tranc[ch]=npy;
                    lpx=s[lpx].pre;
                }
            }
        }
        fin=npx;
    }
    void work(){for(int i=2;i<=size;i++) ans+=s[i].len-s[s[i].pre].len;}
}sam;
void dfs(int x,int f,int fi)
{
    sam.fin=fi,sam.ins(str[x]);
    int fl=sam.fin;
    for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)if(t!=f)
        dfs(t,x,fl);
}
int Iris()
{
    scanf("%d%*d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&str[i]);
    for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),addline(x,y),addline(y,x);
    for(int i=1;i<=n;i++)if(ind[i]==1) dfs(i,0,1);
    sam.work();
    printf("%lld\n",ans);
    return 0;
}
}
int main(){return RKK::Iris();}

原文地址:https://www.cnblogs.com/rikurika/p/12079124.html

时间: 2024-07-31 06:52:34

bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机)的相关文章

【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机

[BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来.也就是说,这n块空地形成了一个树的结构. 有n个粉丝们来到了太阳花田上.为了表达对幽香生日的祝

【bzoj3926】 Zjoi2015—诸神眷顾的幻想乡

http://www.lydsy.com/JudgeOnline/problem.php?id=3926 (题目链接) 题意 给出一棵树,每个节点有一个编号,范围在${[0,9]}$.一个序列是指树上某条路径上的点的编号按顺序依次相接连成的字符串.问有多少个不同的序列. Solution 广义后缀自动机,看起来好高深的样子,然而题解却很简单.这道题好像只是一个很简单的应用吧. 首先题目数据范围有一个很特殊的地方:叶子节点数${<=20}$.嘿嘿嘿,这就可以搞事情了. 我们往叶子节点上想,慢慢就会

[bzoj3926] [loj2137] [Zjoi2015] 诸神眷顾的幻想乡

Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这 \(n\) 块空地之间修建了 \(n-1\) 条边将它们连通起来.也就是说,这 \(n\) 块空地形成了一个树的结构. 有 \(n\) 个粉丝们来到了太阳花田上.为了表达对幽香生日的祝贺,他们选

[Zjoi2015]诸神眷顾的幻想乡

[Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1537  Solved: 892 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条

字符串(广义后缀自动机):BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 843  Solved: 510[Submit][Status][Discuss] Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n

BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡

3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1017  Solved: 599[Submit][Status][Discuss] Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有

【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)

3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 974  Solved: 573 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建

BZOJ 3926 Zjoi2015 诸神眷顾的幻想乡 后缀自动机

题目大意:给定一棵树,每个节点有一个字符,求从一个节点出发沿最短路径走到另一个节点所构成的字符串一共有多少种 此生无悔入东方,来世愿生幻想乡 题目戳这里 注意一句话:太阳花田的结构比较特殊,只与一个空地相邻的空地的数量不超过20个 有奖问答:↑你看到这句话的第一反应是啥? 1.度数<=20 2.叶节点数<=20 仔细看几遍就能找到答案~ [捂脸熊]陈老师真是语文高手.... 叶节点数<=20还做啥了... 直接从每个叶节点DFS一遍,然后构建广义后缀自动机,最终答案就是每个节点的深度-p

P3346 [ZJOI2015]诸神眷顾的幻想乡

$ \color{#0066ff}{ 题目描述 }$ 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来.也就是说,这n块空地形成了一个树的结构. 有n个粉丝们来到了太阳花田上.为了表达对幽香生日的祝贺,他们选择了c中颜色的衣服