洛谷P2408 不同子串个数(后缀自动机)

洛谷 P2408 不同子串个数(后缀数组) 后缀数组 阅读详情

题目

长为n(n<=1e5)的字符串,求其本质不同的子串的个数

思路来源

https://www.luogu.com.cn/blog/user7035/solution-p2408 逆拓扑序

https://www.luogu.com.cn/blog/tanrui-2960967961/solution-p2408 动态维护

https://blog.youkuaiyun.com/Code92007/article/details/82820460 后缀数组

题解

之前学SA的时候,做过这么个题,补一下SAM的做法

可以通过自动机转移和节点维护的字符串两个思路做,

①自动机转移,每个原串的后缀都能到终点被识别,则子串是后缀的一段前缀,对应了自动机上的一段路径

由于SAM是一个DAG,即统计DAG上不同路径的条数,这个按逆拓扑序往回更新一下即可

对于节点u,u如果通过字母c转移到了后继v,则dp[u]+=dp[v]+1(加1是只考虑字母c的这一条路径)

可以通过dfs一下根节点向下记忆化搜索实现,也可以逆拓扑序往回更新实现,这里采用后者

②每个子串仅出现在一个节点里,节点a里出现的子串的长度为[minlen(a),len(a)],

对应贡献了len(a)-minlen(a)+1个子串,动态统计即可

代码1

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
struct SAM{
    struct NODE
    {
        int ch[26];
        int len,fa,sz;
        NODE(){memset(ch,0,sizeof(ch));len=sz=0;}
    }dian[N<<1];
    int las=1,tot=1,len;//rt为1 代表空串
    char s[N];
    void add(int c)
    {
        int p=las;int np=las=++tot;
        dian[np].sz=1;
        dian[np].len=dian[p].len+1;
        for(;p&&!dian[p].ch[c];p=dian[p].fa)dian[p].ch[c]=np;
        if(!p)dian[np].fa=1;//以上为case 1
        else
        {
            int q=dian[p].ch[c];
            if(dian[q].len==dian[p].len+1)dian[np].fa=q;//以上为case 2
            else
            {
                int nq=++tot;dian[nq]=dian[q];
                dian[nq].sz=0;
                dian[nq].len=dian[p].len+1;
                dian[q].fa=dian[np].fa=nq;
                for(;p&&dian[p].ch[c]==q;p=dian[p].fa)dian[p].ch[c]=nq;//以上为case 3
            }
        }
    }
    void init()
    {
        scanf("%d%s",&len,s);
        for(int i=0;i<len;i++)add(s[i]-'a');
    }
}sam;
int c[N<<1],a[N<<1];//c用于基数排序 a用于记录点号
ll ans[N<<1];
int main()
{
    sam.init();
    for(int i=1;i<=sam.tot;++i)c[sam.dian[i].len]++;
    for(int i=1;i<=sam.tot;++i)c[i]+=c[i-1];
    for(int i=1;i<=sam.tot;++i)a[c[sam.dian[i].len]--]=i;
    for(int i=sam.tot;i>=1;--i){//从DAG拓扑序底层开始考虑其后继 逆拓扑序
        int now=a[i];
        for(int j=0;j<26;++j){
            int nex=sam.dian[now].ch[j];
            if(nex){
                ans[now]+=ans[nex]+1;
            }
        }
    }
    printf("%lld\n",ans[1]);
    return 0;
}

代码2

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll res;
struct SAM{
    struct NODE
    {
        int ch[26];
        int len,fa,sz;
        NODE(){memset(ch,0,sizeof(ch));len=sz=0;}
    }dian[N<<1];
    int las=1,tot=1,len;//rt为1 代表空串
    char s[N];
    void add(int c)
    {
        int p=las;int np=las=++tot;
        dian[np].sz=1;
        dian[np].len=dian[p].len+1;
        for(;p&&!dian[p].ch[c];p=dian[p].fa)dian[p].ch[c]=np;
        if(!p)dian[np].fa=1;//以上为case 1
        else
        {
            int q=dian[p].ch[c];
            if(dian[q].len==dian[p].len+1)dian[np].fa=q;//以上为case 2
            else
            {
                int nq=++tot;dian[nq]=dian[q];
                dian[nq].sz=0;
                dian[nq].len=dian[p].len+1;
                dian[q].fa=dian[np].fa=nq;
                for(;p&&dian[p].ch[c]==q;p=dian[p].fa)dian[p].ch[c]=nq;//以上为case 3
            }
        }
        res+=dian[np].len-dian[dian[np].fa].len;//[minlen(a),len(a)]
    }
    void init()
    {
        scanf("%d%s",&len,s);
        for(int i=0;i<len;i++)add(s[i]-'a');
    }
}sam;
int main()
{
    sam.init();
    printf("%lld\n",res);
    return 0;
}

 

基于FPGA与红外成像的眼动追踪系统设计与实现(教学向) 本文详细介绍了基于FPGA与红外成像的眼动追踪系统设计与实现。通过红外摄像头采集图像,利用FPGA进行实时图像处理和红外瞳孔追踪,结合Verilog编程实现多目标检测与瞳孔定位。该系统适用于嵌入式视觉教学,展示了硬件搭建、算法优化及实时显示的完整流程。 阅读详情

相关推荐

别再为Power BI瀑布图发愁了!用这个DAX公式+堆积柱状图,5分钟搞定现金流量表可视化

本文介绍了一种使用DAX公式和堆积柱状图快速实现Power BI现金流量表可视化的高效方法。通过详细的步骤和代码示例,帮助财务分析人员5分钟内完成专业级报表制作,解决传统瀑布图配置复杂、灵活性差的问题,显著提升工作效率。

weixin_28677005的博客 246

luogu2408 不同子串个数

题目背景 因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题: 题目描述 给你一个长为N的字符串,求不同的子串的个数 我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。 子串的定义:原字符串中连续的一段字符组成的字符串 输入输出格式 输入格式: 第一行一个整数N 接下来一行N个字符表示给出的字符串 输...

weixin_30580943的博客 454

使用DeepSeek、MCP和AKShare实现智能金融问答系统技术方案

DeepSeek是由深度求索公司开发的大规模语言模型,最新版本DeepSeek-V3采用混合专家(MoE)架构,拥有671B参数,激活37B参数,在多项基准测试中表现优异3。要使用DeepSeek的API服务:访问DeepSeek平台注册账号获取API Key(形如AKShare是基于Python的金融数据接口库,提供股票、基金、期货、宏观经济等领域的海量数据。主要特点包括:免费开源,数据源丰富支持多种数据格式(DataFrame/JSON)持续更新维护安装命令。

Kin 3173

【洛谷】P2408 不同子串个数

https://www.luogu.com.cn/problem/P2408题目描述: 给你一个长为nnn的字符串,求不同的子串的个数。我们定义两个子串不同,当且仅当有这两个子串长度不一样或者长度一样且有任意一位不一样。子串的定义:原字符串中连续的一段字符组成的字符串。输入格式: 第一行一个整数nnn。接下来一行nnn个字符表示给出的字符串。输出格式: 一行一个整数,表示不一样的子串个数。数据范围: 对于30%30\%30%的数据,保证n≤1000n\le 1000n≤1000。 对于100%100\%10

数学、算法爱好者的博客 907

Python逻辑回归——以车险定价为例(附代码)

保费定价也成为费率厘定,是保险公司运营的环节之一。其过程是根据保单(被保险人)的损失经验和其他相关信息建立模型,并且对未来的保险成本(赔款、代理人佣金、一般管理费用、理赔费用以及支持该业务所需的资本金成本)进行预测的过程。保险公司实际使用的费率还会受到市场供求关系和公司自身发展战略的影响。汽车保险也称机动车辆保险,失意机动车辆本身及其第三者责任等为保险标的的一种运输工具险,在非寿险井算领域中占有重要地位。

m0_62929945的博客 1984

自动驾驶仿真(五)—— 基于Carsim、Prescan、Simulink的联合仿真

自动驾驶仿真五——基于Carsim、Prescan、Simulink的联合仿真1. 联合仿真流程2. CarSim联合仿真配置要点3. Prescan联合仿真配置要点4. Carsim、Prescan、Simulink联合仿真结果5. 参考学习的书目教材 博主前面的博文已经介绍了Carsim和Prescan各自与Matlab/Simulink的相关联合仿真应用实例,并且论述过几款软件各自的优势及用法,CarSim适合动力学模型的建立,PreScan适合行车场景的搭建,Simulink适合控制算法的设计及信号

zhudj08的博客 1万+

HDU6599:求本质不同的子串(回文串)长度及数量

目录 hdu6599题意: manacher+后缀自动机+倍增 \(O(nlog(n))\) manacher+后缀数组+二分 \(O(nlog(n))\) 回文树(回文自动机) \(O(n)\) @(hdu6599:求本质不同的回文串长度及数量) 欢迎交流...

ako2654的博客 1823

抖音直播“卡黑屏”技术解析:从实现原理到平台风控与合规运营

在直播技术领域,视频流推送与实时互动是核心基础。其原理在于通过编码软件(如OBS)将音视频数据封装后,经由网络协议推送到服务器,再分发给观众。这项技术的价值在于支撑了实时、高并发的在线互动场景,是直播、在线会议等应用的基石。然而,在追求流量和互动的实践中,衍生出一些非常规操作,例如通过技术手段中断或控制视频流推送,仅保留音频和互动功能,以达到特定运营目的。这便涉及到了**卡黑屏**这一具体现象。它本质上是对直播流的人为干预,常与**流量博弈**和**风险规避**等动机相关联。从工程实践角度看,实现方式多样,

weixin_29895109的博客 1296

后缀自动机(子串个数)spoj8222

SPOJ Problem Set (classical) 8222. Substrings Problem code: NSUBSTR You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of time

龙崎的专栏 1531

Nano Banana 2哪里使用?Nano Banana 2提示词合集和使用教程

收集最强的Nano Banana 2提示词合集,以及Nano Banana 2哪里使用的教程,并且有10个免费使用渠道。

qq_42927225的博客 1988

基于STM32、HAL库的TLV320AIC3204IRHBR音频接口芯片驱动程序设计

* 开启所有数字部分 */#define TLV320AIC3204_REG_LEFT_HEADPHONE_OUT_VOLUME 0x0C /* 左声道耳机输出音量 */#define TLV320AIC3204_REG_DIGITAL_AUDIO_PATH_CONTROL 0x05 /* 数字音频路径控制 */#define TLV320AIC3204_REG_ANALOG_HP_FILTER_CONTROL 0x34 /* 模拟耳机滤波器控制 *//* 最大音量 */

corlin6688的博客 521

后缀自动机 求不同的子串数目

时间限制:10000ms 单点时限:2000ms 内存限制:512MB 描述小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。现在小Hi想知道一部作品中出现了多少不同的旋律?#include<iostream> #include<cstdio> #include<cstring> #define rg register #define rep(i,x,y) f

Hallelujah520的博客 1544

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【洛谷 P2408】 不同子串个数(后缀自动机)

题目链接 裸体就是身体。 建出\(SAM\),\(DAG\)上跑\(DP\),\(f[u]=1+\sum_{(u,v)\in DAG}f[v]\) 答案为\(f[1]-1\)(因为根节点没有字符) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; cons...

weixin_34347651的博客 211

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

P2408- 不同子串个数【SA】

正题 题目链接:https://www.luogu.com.cn/problem/P2408 题目大意 给出一个字符串,求有多少个不同的子串。 解题思路 进行后缀排序之后,对于位置iii他有n−i+1n-i+1n−i+1个后缀,然后它和排在它前面的后缀有heightiheight_iheighti​个重复的前缀,也就是这么多个重复的子串。对于更前面的后缀的重复在刚刚那一个那里已经减去过了,所以不用统计。 所以答案就是∑i=1nn−i+1−heightsai\sum_{i=1}^nn-i+1-height

QuantAsk 683

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

洛谷 P2408 不同子串个数 题解

洛谷P2408 不同字串个数 题解

glorious_dream的博客 603

洛谷P2408 不同子串个数 后缀数组_Height数组

洛谷P2408 不同子串个数 后缀数组_Height数组 ## 题目描述: 给你一个长为 $N$ $(N&lt;=10^5)$ 的字符串,求不同的子串的个数我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。子串的定义:原字符串中连续的一段字符组成的字符串 很妙的一道题,考察了对 $Height$ 数组的理解。 $...

EM LGH 180

洛谷P2408 不同子串个数

后缀自动机

ACoder 233

洛谷 P2408 不同子串个数

我们可以想到这样的一种计数方法: 后缀[n,n]:有多少个不同串 后缀[n-1,n]:有多少个不同串 后缀[n-2,n]:有多少个不同串 … 最后答案减去重复的串。(发现无法统计答案) 那么改变一下顺序,将这些后缀按照字典序排序后,我们也可以得到另一种顺序来进行计数: 字典序第一小的后缀:有多少个不同串 字典序第二小的后缀:有多少个不同串 字典序第三小的后缀:有多少个不同串 … 我们可以发现,排序以后的,i从2开始,第i个串和第i-1个串,他们相同的串的个数,就是height[i]。 而初始,串的个数一共为

Love_xyh的博客 380

不同子串个数(洛谷P2408紫题)

我们定义两个子串不同,当且仅当有这两个子串长度不一样或者长度一样且有任意一位不一样。子串的定义:原字符串中连续的一段字符组成的字符串。给你一个长为 n 的字符串,求不同的子串的个数。接下来一行 n 个字符表示给出的字符串。一行一个整数,表示不一样的子串个数。请使用64位整数来进行输出。第一行一个整数 n。

lihaoyang321的博客 311

后缀数组求不同子串的个数

后缀数组求不同子串的个数 洛谷P2408 如果学会后缀数组,那么这题就是一个对于后缀数组的结果的应用,具体看solve函数的注释 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> usin...

aihuiju2691的博客 221

【题解】洛谷P2408 不同子串个数

给一个长为n的子串,求不同子串个数,经典题目。 以位置i,i∈[0,n)i,i\in[0,n)i,i∈[0,n)为起点,共有(n−i)(n-i)(n−i)个子串,这其中最多有height[rank[i]]height[rank[i]]height[rank[i]]个串与其它串重复。 结论:不同子串个数等于n∗(n+1)/2−ΣHeightn*(n+1)/2-\Sigma Heightn∗(n+1)...

秋叶红于二月花 606

洛谷P2408 不同子串个数 后缀数组 + Height数组

## 题目描述: 给你一个长为 $N$ $(N<=10^5)$ 的字符串,求不同的子串的个数我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。子串的定义:原字符串中连续的一段字符组成的字符串 很妙的一道题,考察了对 $Height$ 数组的理解。 $1.$首先,不难发现任意子串都可以被字符串中后缀串的前缀表达出来 $2.$我们知道, $Height...

weixin_30526593的博客 92

[洛谷P2408]不同子串个数

题目大意:给你一个字符串,求其中本质不同的字串的个数 题解:同[洛谷P4070][SDOI2016]生成魔咒,只要最后再输出就行了 卡点:无 C++ Code: #include <cstdio> #include <map> #define maxn 100010 long long ans; namespace SAM { #define N...

weixin_34194551的博客 179

【ybt金牌导航2-3-2】【luogu P2408】不同子串数(三种做法)

给你一个字符串,问你它有多少个不同的子串。

欢迎您的光顾awa 288
上一篇: 洛谷P3804 【模板】后缀自动机 (SAM) (后缀自动机)
下一篇: 牛客2018 牛客国庆集训派对Day6 A.Birthday(最小费用流 板子题)
小衣同学
博客等级 码龄9年 1444粉丝 995原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值