算法——后缀自动机

算法总结:DFA(自动机)算法是什么,怎么用 算法总结:高手们常说的DFA(自动机)算法是什么简介一:从一个C++语言程序开始1.基础C语言解法2.DFA(自动机)算法思想3.自动机编程题解二:Leetcode实战注 简介 自动机编程(英语:Automata-based programming) 是编程典范中的一种,是指程式或其中的部份是以有限状态机(FSM)为模型的程式,有些程式则会用其他型式(也更复杂)的自动机为其模型。自动机程序在每个时刻有一个状态 s,每次经过一个行动 f,转移到下一个状态 s’。这样,只需要建立一个覆盖所有情况的从 s 与 f 阅读详情

后缀自动机初相识

在字符串处理的广袤领域中,后缀自动机(Suffix Automaton,简称 SAM)宛如一颗璀璨的明珠,散发着独特的魅力。它是一种强大的数据结构,如同一位技艺精湛的工匠,能够高效地处理各种复杂的字符串问题,为我们在字符串的迷宫中指引方向。

后缀自动机可以被看作是一个有向无环图(DAG),其中每个顶点代表一个状态,每条有向边则表示状态之间的转移。在这个奇妙的图中,从初始状态出发,沿着任意路径前进,将路径上经过的边所标记的字符依次连接起来,得到的字符串必然是原字符串的一个子串。反之,原字符串的每一个子串也都能在这个图中找到对应的唯一路径。这种一一对应的关系,使得后缀自动机能够简洁而高效地存储和表示字符串的所有子串信息 ,就像是一个精心整理的图书馆,每一本书(子串)都能在书架(后缀自动机)上迅速找到。

例如,对于字符串 “abab”,其后缀自动机可以形象地表示为一个包含多个状态和转移边的图。从初始状态开始,通过转移边依次经过字符 ‘a’、‘b’、‘a’、‘b’,可以得到原字符串的所有子串,如 “a”、“ab”、“aba”、“abab” 等。每个子串都对应着图中的一条路径,这种直观的映射关系,让我们能够更清晰地理解后缀自动机的工作原理。

后缀自动机的原理剖析

(一)基本概念

后缀自动机是接收字符串所有后缀的最小化确定有限状态自动机。从直观上来看,它是一张有向无环图(DAG) ,其中的顶点代表状态,边代表状态之间的转移。它存在一个特殊的初始状态,从这个初始状态出发,可以到达其余的所有状态。自动机中的每一条转移边都被特定的符号标记,且从同一个状态出发的不同转移边,其标记的符号是不同的。同时,存在一个或多个状态被标记为终止状态,从初始状态出发,沿着任意路径走到终止状态,将路径上经过的边的标记依次连接起来,所得到的字符串必定是原字符串的一个后缀 。并且,后缀自动机是在满足上述条件的所有自动机中,顶点数最少的那个。

(二)关键性质

子串信息完备性:后缀自动机包含了原字符串的所有子串信息。这意味着,从初始状态出发,沿着自动机中的任意路径前进,将路径上的边的标记依次连接起来,所得到的字符串必然是原字符串的一个子串;反之,原字符串的任意一个子串,都能在后缀自动机中找到一条对应的路径 。这种一一对应的关系,使得后缀自动机成为了一个高效存储和处理字符串子串信息的数据结构。

endpos 概念及性质:对于原字符串的任意非空子串 ttt,定义 endpos(t)endpos(t)endpos(t) 为 ttt 在原字符串中所有出现位置的终点集合。例如,对于字符串 “banana”,子串 “ana” 的 endpos(ana)={3,5}endpos(ana)=\{3, 5\}endpos(ana)={3,5}。两个子串 t1t_1t1​ 和 t2t_2t2​,如果 endpos(t1)=endpos(t2)endpos(t_1)=endpos(t_2)endpos(t1​)=endpos(t2​),则称它们是终点等价的。所有非空子串可以根据终点等价性分成若干类。在后缀自动机中,每个状态对应一个或多个拥有相同终点集合的子串,即后缀自动机中的状态数等于所有子串的终点等价类个数加上初始状态。关于 endposendposendpos 还有以下重要性质:

若两个非空子串 uuu 和 vvv(∣u∣≤∣v∣|u|\leq|v|∣u∣≤∣v∣)终点等价,那么 uuu 在原字符串中仅作为 vvv 的后缀出现。

对于两个非空子串 uuu 和 vvv(∣u∣≤∣v∣|u|\leq|v|∣u∣≤∣v∣),它们的终点集合要么不相交,要么 endpos(v)endpos(v)endpos(v) 是 endpos(u)endpos(u)endpos(u) 的子集,这取决于 uuu 是否是 vvv 的后缀。

将一个终点等价类中的子串按长度递减排序,每个子串都是前一个子串的后缀,它们的长度依次取区间 [x,y][x,y][x,y] 内的所有数 。

后缀链接(suffix link):对于后缀自动机中除初始状态外的某个状态 vvv,设与该状态对应的子串集合中最长的子串为 www,那么存在一个 www 的后缀 ttt,它是 www 的最长后缀且与 www 不在同一个终点等价类中,从状态 vvv 到对应 ttt 的状态的链接就是后缀链接,记为 link(v)link(v)link(v)。所有的后缀链接构成了一棵以初始状态为根的树,称为后缀链接树。通过后缀链接,可以方便地在后缀自动机中进行各种操作,例如查找某个子串的最长公共后缀等。 后缀链接的存在,进一步增强了后缀自动机处理字符串问题的能力,使得我们能够在更复杂的字符串操作中,高效地利用后缀自动机的结构。

后缀自动机的构建算法

(一)在线构建算法解析

后缀自动机的构建算法中,在线构建算法是一种非常高效且常用的方法。它的核心思想是通过逐步添加字符的方式,动态地构建后缀自动机。这种方式就像是在搭建一座积木塔,每添加一个字符,就像是在塔上添加一块积木,不断完善整个结构 。

下面我们以一个具体的字符串为例,详细解释在线构建算法的每一步。假设我们要构建字符串 “abab” 的后缀自动机。首先,我们初始化后缀自动机,它包含一个初始状态,这个初始状态就像是一个起点,所有的构建都从这里开始。

然后,我们开始逐个添加字符。当添加第一个字符 ‘a’ 时,我们从初始状态出发,创建一个新的状态,这个新状态表示字符串 “a”。从初始状态到这个新状态有一条标记为 ‘a’ 的边,表示通过 ‘a’ 可以从初始状态转移到这个新状态。此时,后缀自动机中只有两个状态和一条边。

接着添加字符 ‘b’。我们从当前表示字符串 “a” 的状态出发,发现没有标记为 ‘b’ 的边,于是创建一个新的状态,表示字符串 “ab”,并在表示 “a” 的状态和这个新状态之间添加一条标记为 ‘b’ 的边。此时,后缀自动机中已经有了三个状态和两条边,它可以表示字符串 “a” 和 “ab”。

当添加第三个字符 ‘a’ 时,从表示 “ab” 的状态出发,没有标记为 ‘a’ 的边,所以创建新状态表示 “aba”,并添加相应的边。此时,后缀自动机的结构进一步丰富,能够表示更多的子串。

在添加字符的过程中,还涉及到后缀链接的更新。后缀链接的作用是将一个状态连接到它所代表的最长子串的最长后缀所在的状态。例如,对于表示 “aba” 的状态,它的后缀链接会指向表示 “a” 的状态,因为 “a” 是 “aba” 的最长后缀且与 “aba” 不在同一个终点等价类中。通过后缀链接,我们可以方便地在后缀自动机中进行各种操作,如查找最长公共后缀等。

在实际的代码实现中,我们可以使用结构体来表示后缀自动机的状态,每个状态包含转移边的信息、后缀链接以及该状态所代表的子串的长度等。以下是一个简化的 C++ 代码示例,用于构建后缀自动机:


const int MAXN = 100005;

const int CHARSET = 26;

struct SuffixAutomaton {

   int ch[MAXN * 2][CHARSET];

   int len[MAXN * 2];

   int fa[MAXN * 2];

   int sz, last;

   SuffixAutomaton() {

       sz = last = 1;

   }

   void extend(int c) {

       int p = last;

       int np = ++sz;

       last = np;

       len[np] = len[p] + 1;

       for (; p &&!ch[p][c]; p = fa[p]) {

           ch[p][c] = np;

       }

       if (!p) {

           fa[np] = 1;

       } else {

           int q = ch[p][c];

           if (len[q] == len[p] + 1) {

               fa[np] = q;

           } else {

               int nq = ++sz;

               len[nq] = len[p] + 1;

               fa[nq] = fa[q];

               fa[q] = fa[np] = nq;

               memcpy(ch[nq], ch[q], sizeof(ch[q]));

               for (; p && ch[p][c] == q; p = fa[p]) {

                   ch[p][c] = nq;

               }

           }

       }

   }

};

在这段代码中,extend 函数用于添加一个字符。首先创建一个新的状态 np,并更新其长度。然后通过 p 从当前的最后一个状态开始,沿着后缀链接向上查找,对于没有指向 np 的转移边的状态,添加这条转移边。如果 p 最终变为 0,说明没有找到之前已经存在的以 c 为转移边的状态,那么 np 的后缀链接就指向初始状态。如果找到了这样的状态 q,并且 q 的长度等于 p 的长度加 1,说明 q 就是 np 的后缀链接应该指向的状态。否则,需要创建一个新的状态 nq,将 q 的信息复制到 nq,并调整后缀链接和转移边,以保证后缀自动机的正确性。

(二)复杂度分析

后缀自动机的构建算法在时间和空间复杂度上都表现出了优秀的性能。在时间复杂度方面,对于长度为 nnn 的字符串,在线构建后缀自动机的时间复杂度为 O(n)O(n)O(n)。这是因为在添加每个字符时,虽然有循环操作,但每个状态最多被访问一次,并且每次访问的操作都是常数时间的,所以总体时间复杂度是线性的。例如,在构建字符串 “abab” 的后缀自动机时,我们添加四个字符,每个字符的添加过程中,状态的遍历和操作都是有限的,不会随着字符串长度的增加而出现指数级的增长。

在空间复杂度上,后缀自动机的状态数最多为 2n−12n - 12n−1,其中 nnn 是字符串的长度。这是因为后缀自动机是一个有向无环图,每个状态代表一个或多个子串的等价类,随着字符的添加,新的状态不断产生,但总体数量是有限的。每个状态需要存储转移边和后缀链接等信息,假设字符集大小为 mmm,那么每个状态需要 O(m)O(m)O(m) 的空间来存储转移边,所以后缀自动机的空间复杂度为 O(nm)O(nm)O(nm)。当字符集大小 mmm 为常数时,空间复杂度可以近似看作 O(n)O(n)O(n)。这种优秀的时空复杂度,使得后缀自动机在处理长字符串时具有很大的优势,能够高效地存储和处理字符串的各种信息 。例如,在处理一篇很长的文档时,后缀自动机可以快速地构建并提供对文档中各种子串的查询和分析能力,而不会占用过多的内存和时间。

后缀自动机的应用领域

(一)字符串匹配

在文本处理的众多场景中,字符串匹配是一项基础而关键的任务。后缀自动机凭借其独特的结构和高效的算法,在字符串匹配领域展现出了卓越的性能。例如,在搜索引擎中,当用户输入关键词进行搜索时,搜索引擎需要在海量的文本数据中快速查找包含该关键词的文档。后缀自动机可以将文档内容构建成后缀自动机,然后通过在后缀自动机上进行模式匹配,迅速定位到关键词在文档中的所有出现位置 。

具体实现时,我们从后缀自动机的初始状态开始,根据待匹配字符串的字符依次沿着转移边进行状态转移。如果在某个状态下能够成功匹配当前字符并转移到下一个状态,就继续匹配下一个字符;如果无法转移,则说明待匹配字符串在该位置不匹配。当成功匹配完待匹配字符串的所有字符时,就找到了一个匹配位置。例如,对于文本字符串 “banana” 和模式字符串 “ana”,我们从后缀自动机的初始状态出发,依次匹配字符 ‘a’、‘n’、‘a’,沿着相应的转移边成功到达目标状态,从而确定 “ana” 在 “banana” 中出现的位置。这种匹配方式的时间复杂度为 O(m)O(m)O(m),其中 mmm 是待匹配字符串的长度,相比传统的暴力匹配算法,大大提高了匹配效率。

(二)子串统计

后缀自动机在子串统计问题上也有着出色的表现。统计不同子串个数是字符串处理中的一个常见问题,利用后缀自动机可以轻松解决。由于后缀自动机包含了原字符串的所有子串信息,我们可以通过对后缀自动机的状态进行分析来统计不同子串的个数。每个状态所代表的子串集合中,不同长度的子串都是不同的,并且不同状态所代表的子串集合也是不同的。因此,我们可以通过累加每个状态所代表的不同长度子串的数量来得到不同子串的总个数 。

以字符串 “abab” 为例,其后缀自动机中的每个状态对应着不同的子串集合。初始状态代表空串,从初始状态出发,通过不同的转移边可以到达代表 “a”、“ab”、“aba”、“abab” 等子串的状态。每个状态所代表的子串集合中,子串的长度是不同的,我们可以通过计算每个状态所代表的子串集合中不同长度子串的数量,然后将所有状态的数量累加起来,就得到了字符串 “abab” 的不同子串个数。在实际代码实现中,可以通过深度优先搜索(DFS)或拓扑排序等方法遍历后缀自动机的状态,统计不同子串的个数。

统计子串出现次数也是后缀自动机的一个重要应用。我们可以在构建后缀自动机的过程中,记录每个状态所代表的子串的出现次数。当处理完整个字符串后,通过后缀链接和状态转移关系,可以计算出每个子串的出现次数。例如,对于字符串 “banana”,我们可以通过后缀自动机计算出子串 “ana” 出现的次数。这种方法在处理大规模文本数据时,能够高效地统计出各种子串的出现情况,为文本分析提供有力的支持。

(三)其他应用场景拓展

后缀自动机的应用不仅仅局限于字符串处理领域,它在计算机视觉领域也有着广泛的应用前景。在图像分割中,后缀自动机可以将图像的像素信息或特征信息看作是字符串,通过构建后缀自动机来寻找图像中的相似区域或模式,从而实现图像的分割。例如,在医学图像分析中,后缀自动机可以帮助医生快速准确地分割出病变区域,为疾病的诊断和治疗提供重要的依据。

在目标检测中,后缀自动机可以用于提取目标物体的特征字符串,并通过在图像中搜索这些特征字符串来检测目标物体的存在和位置。这种方法能够有效地处理复杂背景下的目标检测问题,提高检测的准确性和效率。例如,在自动驾驶系统中,后缀自动机可以帮助车辆快速识别道路上的行人、车辆等目标物体,保障行车安全。

后缀自动机作为一种强大的数据结构,在多个领域都有着重要的应用价值。随着技术的不断发展和创新,后缀自动机的应用场景还将不断拓展,为解决各种复杂问题提供新的思路和方法。

实战演练:后缀自动机解题实例

(一)题目描述

给定一个长度为 nnn 的字符串 sss,由小写英文字母组成,求该字符串中不同子串的个数 。例如,对于字符串 “abab”,其不同子串有 “a”、“b”、“ab”、“ba”、“aba”、“bab”、“abab”,共 7 个。

(二)思路分析

根据后缀自动机的性质,每个状态对应一个或多个具有相同终点集合的子串。对于每个状态,其代表的不同子串数量等于该状态所代表的最长子串长度减去其后缀链接所指向状态代表的最长子串长度(因为后缀链接指向的是其最长后缀且不在同一终点等价类的状态)。

我们可以通过构建后缀自动机,然后遍历后缀自动机的所有状态,累加每个状态所代表的不同子串数量,从而得到字符串中不同子串的总数。在构建后缀自动机时,使用在线构建算法,按照字符顺序依次添加字符,动态更新后缀自动机的结构 。

(三)代码实现与解析

下面是使用 C++ 实现的代码:


#include <iostream>

#include <cstring>

using namespace std;

const int MAXN = 100005;

const int CHARSET = 26;

struct SuffixAutomaton {

   int ch[MAXN * 2][CHARSET];

   int len[MAXN * 2];

   int fa[MAXN * 2];

   int sz, last;

   SuffixAutomaton() {

       sz = last = 1;

   }

   void extend(int c) {

       int p = last;

       int np = ++sz;

       last = np;

       len[np] = len[p] + 1;

       for (; p &&!ch[p][c]; p = fa[p]) {

           ch[p][c] = np;

       }

       if (!p) {

           fa[np] = 1;

       } else {

           int q = ch[p][c];

           if (len[q] == len[p] + 1) {

               fa[np] = q;

           } else {

               int nq = ++sz;

               len[nq] = len[p] + 1;

               fa[nq] = fa[q];

               fa[q] = fa[np] = nq;

               memcpy(ch[nq], ch[q], sizeof(ch[q]));

               for (; p && ch[p][c] == q; p = fa[p]) {

                   ch[p][c] = nq;

               }

           }

       }

   }

};

int main() {

   string s;

   cin >> s;

   SuffixAutomaton sam;

   for (int i = 0; i < s.length(); i++) {

       sam.extend(s[i] - 'a');

   }

   long long ans = 0;

   for (int i = 2; i <= sam.sz; i++) {

       ans += sam.len[i] - sam.len[sam.fa[i]];

   }

   cout << ans << endl;

   return 0;

}

代码解析:

结构体定义:SuffixAutomaton 结构体定义了后缀自动机的相关信息,包括状态转移数组 ch、子串长度数组 len、后缀链接数组 fa,以及当前状态数量 sz 和最后一个状态 last。

extend** 函数**:用于向后缀自动机中添加一个字符。首先创建一个新状态 np,其长度为前一个状态 p 的长度加 1。然后从 p 开始,沿着后缀链接向上查找,对于没有指向 np 的转移边的状态,添加这条转移边。如果找到了这样的状态 q,并且 q 的长度等于 p 的长度加 1,说明 q 就是 np 的后缀链接应该指向的状态。否则,需要创建一个新的状态 nq,将 q 的信息复制到 nq,并调整后缀链接和转移边 。

主函数:读取输入字符串,逐个字符添加到后缀自动机中。最后,遍历后缀自动机的所有状态(从状态 2 开始,因为状态 1 是初始状态,不代表实际子串),累加每个状态所代表的不同子串数量,即 len[i] - len[fa[i]],得到不同子串的总数并输出。

总结与展望

后缀自动机作为一种强大而高效的数据结构,在字符串处理领域展现出了独特的魅力和卓越的性能。它通过巧妙的状态压缩和转移机制,能够以线性的时空复杂度处理各种复杂的字符串问题,为我们解决实际问题提供了有力的工具。

从原理上看,后缀自动机基于字符串的后缀信息和 endpos 等价类的概念,构建了一个紧凑而高效的有向无环图结构。这种结构不仅能够完整地表示字符串的所有子串,还通过后缀链接等特性,为各种字符串操作提供了便捷的途径。

在构建算法上,在线构建算法的巧妙设计使得后缀自动机能够逐步添加字符,动态地构建出完整的结构,并且保证了线性的时间复杂度。这种高效的构建方式使得后缀自动机在处理大规模字符串数据时具有明显的优势。

在应用方面,后缀自动机广泛应用于字符串匹配、子串统计等多个领域,为文本处理、信息检索、生物信息学等实际问题提供了高效的解决方案。通过实际的代码实现和案例分析,我们也看到了后缀自动机在解决具体问题时的强大能力和灵活性。

然而,后缀自动机的学习和应用也并非一蹴而就,需要我们深入理解其原理和算法,通过大量的实践来掌握其使用技巧。同时,随着技术的不断发展,我们也可以期待后缀自动机在更多领域得到应用和拓展,与其他技术相结合,产生更多创新的解决方案。希望读者能够通过本文的介绍,对后缀自动机有更深入的理解和认识,并在实际项目中充分发挥它的优势,解决更多的实际问题。

蓝桥杯算法解析(十三):字符串高级算法——后缀自动机与回文树 字符串处理是算法竞赛中最具挑战性的领域之一,在蓝桥杯国赛中占比高达30%。本文将深入探讨字符串处理的两大高级数据结构——后缀自动机和回文树,通过系统化的理论讲解和实战案例分析,帮助读者攻克字符串难题。 阅读详情

相关推荐

# 蓝桥杯算法解析(十六):字符串匹配终极算法——后缀自动机与回文自动机

字符串处理是算法竞赛中最具挑战性的领域之一,在蓝桥杯国赛中占比高达30%。本文将深入探讨字符串匹配的两大终极武器——后缀自动机和回文自动机,通过系统化的理论讲解和实战案例分析,帮助读者掌握这些顶尖的字符串处理技术。

资深全栈架构师,乐于在 优快云 分享技术见解,与大家携手共进,共攀技术巅峰! 1167

后缀自动机(知识整理+板子总结)

后缀自动机(知识整理+板子总结)

小衣同学的博客 5366

后缀自动机实现字典序子串搜索的算法解析

字典序子串搜索是字符串处理中的经典问题,要求高效找到给定字符串中第k小的子串。后缀自动机(SAM)因其独特的拓扑结构,成为解决此类问题的理想数据结构。通过构建状态转移图和后缀链接树,SAM能以O(n)空间存储所有子串信息。预处理阶段采用动态规划统计各状态子串数量,查询时通过字典序遍历转移边实现亚线性时间响应。该技术在文本搜索引擎、基因组序列分析等场景有重要应用,特别是处理大规模数据时,相比传统后缀数组方案具有明显性能优势。算法实现中需注意重复子串处理、内存优化等工程细节,本文展示的Python/C++代码示

weixin_33552698的博客 345

【学习笔记】后缀自动机(SAM)

对于一个子串ttt,它在原串sss里面的结束位置集合记为endpostendpos_tendpost​比如sabcbcs = abcbcsabcbctbct = bctbc,那么endpost24endpost​24(假设字符串从0开始编号)

Brute♂force 1574

电子元器件基础:电阻、电容、电感的特性与应用解析

本文深入解析了电子元器件中电阻、电容和电感三大基础元件的核心特性、工作原理与选型应用。电阻作为电路中的‘交通警察’,控制电流与分配电压,其额定功率与精度是关键选型参数。文章结合实战经验,详细阐述了它们在电源滤波、信号处理及高频电路中的不同表现与避坑指南,是电子设计与维修的必备基础知识。

weixin_29213655的博客 376

Spring AI Alibaba Graph进阶:如何用图算法优化你的推荐系统?

本文深入探讨了如何利用Spring AI Alibaba Graph的图算法优化推荐系统。通过分析用户行为数据的网络化特征,结合加权随机游走和社区发现算法,显著提升推荐精准度和用户点击率。文章还分享了混合推荐架构设计、性能优化技巧及生产环境中的实战经验,为开发者提供了一套完整的图算法推荐解决方案。

weixin_33738555的博客 128

【学习笔记】后缀自动机SAM

学了 24 个小时都没学懂……

七代目鸽影 4243

Vivado安装教程:多版本共存的配置技巧

详解Vivado安装教程中的多版本共存配置技巧,帮助用户在同一系统中管理不同版本的Vivado开发环境,提升开发效率与兼容性,适用于需要切换版本的FPGA开发者。

weixin_35257663的博客 1774

后缀自动机(SAM)讲解 + Luogu p3804【模板】后缀自动机 (SAM)

后缀自动机 SAM

Jacob0824的博客 3049

从原理到实践:详解双目散斑结构光的生成与优化

本文深入解析了双目散斑结构光的生成原理与优化实践,详细介绍了散斑结构光的抗干扰性、空间编码技术及其在三维视觉中的应用。通过对比不同生成方法和技术路线,提供了参数调优指南和工程实现细节,帮助开发者掌握高效、精准的散斑生成技术。

weixin_42521856的博客 591

从零开始:如何在Windows上搭建Airsim仿真环境(避坑指南)

本文是一份详细的Windows平台AirSim仿真环境搭建指南。文章从硬件要求、Visual Studio与虚幻引擎安装开始,逐步讲解AirSim插件编译、UE项目配置,并重点介绍了通过WSL2连接PX4飞控软件实现软件在环仿真的完整流程。内容涵盖常见问题排查与性能优化,旨在帮助开发者避开常见陷阱,高效构建可用于无人机算法开发的虚拟测试平台。

earth的博客 300

算法复习——后缀自动机

讲解: 这里套用functioner神犇的文章,ORZ·····,原网址:http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html 星期五的时候,在网上看别人的总结看了很久也没有什么收获,不过星期六看了clj原汁原味的论文,终于明白了(网上的总结只写了大致做法,比较难理解). 后缀自动机实质上是字母树,记录的字符串是某...

banzhangzhi8819的博客 117

system_server_lowmem真的是内存不足吗?

Android系统中的system_server_lowmem真的表示系统的内存遇到瓶颈了吗?以及遇到这类日志该如何分析系统的内存,本文会回答这个问题。

jidapenglin28的专栏 513

算法详解——后缀自动机

由于最近优快云对Markdown的支持不好,因此贴出Markdown代码:https://paste.ubuntu.com/p/Wd8PJnnxTf/ DFA ////////////////////////////////////////////////////////////////////////// DFA,即确定性有限状态自动机,由一个五元组M=(Σ,Q,qs,F,tr)M=(Σ...

Canopus 339

Python爬虫实战:公共资源交易平台招标数据采集实战 - 从零构建企业情报系统(附CSV导出 + SQLite持久化存储)!

我长期专注 Python 爬虫工程化实战,主理专栏 👉 《Python爬虫实战》:从采集策略到反爬对抗,从数据清洗到分布式调度,持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”,让数据价值真正做到——抓得到、洗得净、用得上。

喵手的博客 1288

2024美团秋招硬件开发笔试真题及答案解析

在 Linux 内核的网络设备驱动中,数据链路层的功能通常由网络协议栈的低层(如以太网驱动)实现,而不是作为网络设备驱动的一个独立层次。在 FreeRTOS 中,任务通知(Task Notifications)是一种轻量级的事件传递机制,用于在任务之间或任务与中断之间传递信号。小美正在开发一个简单的密码生成器,其中一个功能是将输入的字符串中的所有字母按字母顺序循环前移一位(即 'a' 变为 'z','B' 变为 'A',以此类推)。它包含了网络设备的各种参数和方法,用于管理网络设备的初始化、配置和操作。

XU157303764的博客 1675

4.13 ACM-ICPC算法 字符串之后缀自动机(SAM)

在竞赛编程,尤其是ACM-ICPC竞赛中,字符串算法占据了极其重要的位置。其中,后缀自动机(Suffix Automaton, 简称SAM)以其强大的功能和高效的性能,成为了解决字符串问题的利器。本文旨在介绍后缀自动机的基本概念、构建方法以及在算法竞赛中的应用示例。

tang7mj的博客 1271

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

codeforces-go中的字符串算法:后缀自动机应用

后缀自动机(Suffix Automaton, SAM)是处理字符串问题的高效数据结构,能在**线性时间**内构建,支持多种复杂字符串操作。在codeforces-go项目中,SAM实现位于[copypasta/sam.go](https://link.gitcode.com/i/5cccf7002d1aade4bab77ca6576a40c2),本文将从基础原理到实际应用,详解其在算法竞赛中的核

gitblog_01065的博客 1047

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

后缀自动机模板题详解:从算法思路到代码实现(以 P3804 为例)

你是否在为处理大规模字符串子串统计问题而发愁?后缀自动机(SAM)作为高效处理字符串的 “利器”,能在线性时间内解决子串出现次数、最长子串等复杂问题。本文以洛谷 P3804 模板题为例,手把手拆解 SAM 核心原理:从状态定义、构建过程到拓扑排序统计出现次数,结合详细代码注释与例题分析,帮你快速掌握这一算法。

2301_79279099的博客 711

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

后缀自动机算法复习回顾

快速复习一下,怕忘了

DD(XYX)的硫氰化氘博客 195

算法学习:后缀自动机

【前置知识】 AC自动机(没有什么关联,但是看懂了会对后缀自动机有不同的理解) 【解决问题】 各种子串的问题 【算法学习】 学习后缀自动机的过程中,看到了许多相关性质和证明,但是奈何才疏学浅(lan) 暂时先放着,到有空再更 【算法分析】 后缀自动机和AC自动机和回文自动机的不同点在于 后缀自动机是个DAG,而AC自动机和回文自动机是树 ...

weixin_30535913的博客 161

【算法与数据结构】——后缀自动机

参考博客史上最通俗的后缀自动机详解

气派飞鹰的博客 1571

【牛客 - 551C】CSL 的密码(后缀数组,后缀自动机,随机算法)

题干: 链接:https://ac.nowcoder.com/acm/contest/551/C 来源:牛客网 为了改变这一点,他决定重新设定一个密码。于是他随机生成了一个很长很长的字符串,并打算选择一个子串作为新密码。他认为安全的密码长度至少为 m,那么他有多少种不同选择方式呢?两种方案不同,当且仅当选出的密码内容不同。 输入描述: 第一行有两个整数 n 和 m ,分别表示 CSL...

xuanweiace的博客 695

算法模板:后缀自动机模板

pascal后缀自动机模板  //后缀自动机模板 var i,last,q,p,total,x,cur,clo:longint; s:ansistring; n:int64; bz:boolean; len,link:array[0..150000]of longint; //len——节点i到0的最短路,link——状态i的(来源?) son:array[0..150000,1....

JZHu_Ming_Han的博客 330

算法学习:后缀自动机转后缀树转后缀数组

算法学习:后缀自动机转后缀树转后缀数组 引入 其实这是一篇水文 想要学后缀自动机的话去查2012年noi冬令营陈立杰讲稿 顺便说一句,讲稿上有一些错误,多翻几篇博客加深理解。 今天这里主要要讲的是后缀自动机如何转后缀树和后缀数组 后缀树 这里首先需要提一下后缀树的概念 后缀树其实相当于把所有的后缀插入一颗Trie树 然而时空复杂度都是O(N^2)的 所以我们可以把这可T

maxtir的博客 3205
上一篇: 算法——后缀平衡树
下一篇: java——执行linux/cmd命令
夏子曦
夏子曦 优质创作者: 产品设计技术领域 优质创作者: 产品设计技术领域
博客等级 码龄15年 8289粉丝 427原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值