自己主动机串标:Directed Acyclic Word Graph

简介:

trie -- suffix tree -- suffix automa 有这么几个情况:

用户输入即时响应AJAX搜索框, 显示候选名单。
搜索引擎keyword统计数量。




后缀树(Suffix Tree): 从根到叶子表示一个后缀。

只从这一个简单的描写叙述,我们能够概念上解决以下的几个问题:

P:查找字符串o是否在字符串S中
A:若o在S中,则o必定是S的某个后缀的前缀。 用S构造后缀树。按在trie中搜索字串的方法搜索o就可以。

 

P: 指定字符串T在字符串S中的反复次数。
A: 假设T在S中反复了两次,则S应有两个后缀以T为前缀,搜索T节点下的叶节点数目即为反复次数。

P: 字符串S中的最长反复子串。
A: 同上。找到最深的非叶节点T。

P: 两个字符串S1。S2的最长公共子串。
A: 广义后缀树(Generalized Suffix Tree)存储_多个_字符串各自的全部后缀。把两个字符串S1#。S2$增加到广义后缀树中,然后同上。


(A longest substring common to s1 and s2 will be the path-label of an internal node with the
greatest string depth in the suffix tree which has leaves labelled with suffixes from both the
strings.)

Suffix Automa: 识别文本全部子串的辅助索引结构。


以下的代码是直接翻译[1]中算法A:

/*Directed Acyclic Word Graph

*/
#include <stdlib.h>
#include <string.h>

typedef struct State{
	struct State *first[26], *second[26];
	struct State *suffix;
}State;

State *sink, *source;

State *new_state(void)
{
	State *s = malloc(sizeof *s);
	if(s){
		memset(s, 0, sizeof *s);
	}
	return s;	
}

/*state:
 parent -- [x] with xa = tail(wa)
 child  -- [tail(wa)]
 new child -- [tail(wa)]_{wa}
*/
State *split(State *parent, int a)
{
	int i;
	/*current state, child, new child*/
	State *cs = parent, *c = parent->second[a], *nc = new_state(); //S1
	parent->first[a] = parent->second[a] = nc; //S2
	for(i = 0; i < 26; ++i){
		nc->second[i] = c->second[i]; //S3
	}	
	nc->suffix = c->suffix; //S4
	c->suffix = nc; //S5
	
	for(cs = parent; cs != source; ){//S6,7
		cs = cs->suffix; //S7.a
		for(i = 0; i < 26; ++i){
			if(cs->second[i] == c)cs->second[i] = nc; //S7.b
			else goto _out; //S7.c
		}
	}	
_out:
	return nc; //S8
}

/*state:
 new sink -- [wa] 
*/
void update(int a)
{
	/*suffix state, current state, new sink*/
	State *ss = NULL, *cs = sink, *ns = new_state(); //U1,2 
	sink->first[a] = ns;
	
	while(cs != source && ss == NULL){//U3
		cs = cs->suffix; //U3.a	
		if(!cs->first[a] && !cs->second[a]){
			cs->second[a] = ns; //U3.b.1
		}else if(cs->first[a]){
			ss = cs->first[a]; //U3.b.2	
		}else if(cs->second[a]){
			ss = split(cs, a); //U3.b.3
		}
	}

	if(ss == NULL){ss = source;} //U4
	ns->suffix = ss; sink = ns; //U5
}

int build_dawg(char *w)
{
	sink = source = new_state();
	for(; *w; ++w){update(*w-'a');}
}


我还在努力理解中,没有測试。


[1] the smallest automation recognizing the subwords of a text 

 https://cbse.soe.ucsc.edu/sites/default/files/smallest_automaton1985.pdf


版权声明:本文博客原创文章,博客,未经同意,不得转载。







本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4739130.html,如需转载请自行联系原作者


相关文章
|
12月前
|
存储 缓存 调度
性能提升利器|PolarDB- X 超详细列存查询技术解读
本文将深入探讨 PolarDB-X 列存查询引擎的分层缓存解决方案,以及其在优化 ORC 列存查询性能中的关键作用。
1467 69
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
1049 0
|
存储 缓存 弹性计算
重新审视 CXL 时代下的分布式内存
从以太网到 RDMA 再到 CXL,标志着互连技术的重大突破。
|
监控 安全 网络安全
云计算与网络安全:构建安全的云端未来
在当今这个数字化时代,云计算已成为推动技术创新和服务交付的重要力量。然而,随着云服务的普及,网络安全和信息安全的挑战也日益凸显。本文探讨了云计算的基本概念、面临的安全威胁以及采取的防护措施,旨在揭示如何通过先进技术和管理策略确保云环境的安全性。通过对现有技术的分析,本文展示了保护数据和基础设施免受网络攻击的可能性和重要性,为未来的云安全提供了方向。
164 1
|
缓存 JavaScript
vue组件强制刷新的5种方案
vue组件强制刷新的5种方案
1319 2
|
存储 算法 开发者
Lucene底层关键字数据结构(FST状态机) | 学习笔记
快速学习Lucene底层关键字数据结构(FST状态机)。
Lucene底层关键字数据结构(FST状态机) | 学习笔记
|
算法 测试技术 编译器
【算法】优先队列式分支限界法,以01背包问题为例
📑 例题:01背包问题 题目链接:采药-洛谷 当洛谷上不让下载测试用例,可以试试:采药-ACWing
1786 0
|
消息中间件 存储 监控
消息队列与任务队列的区别
消息队列和任务队列是我们在软件系统中常常遇到的概念。尽管它们的名字相似,但实际上它们有不同的用途和工作原理。本文将介绍消息队列和任务队列之间的区别。
838 0
|
数据挖掘 数据格式
R语言- ComplexHeatmap 绘制复杂热图示例
ComplexHeatmap是R语言中用于绘制复杂热图的一个重要包。它提供了一种灵活、高效、易于定制的方法来绘制热图,并支持多种数据类型和数据格式,支持包括多种热图类型,包括基本热图、聚类热图、分组热图、矩阵热图等。用户可以根据自己的需求选择不同的热图类型,并进行灵活的定制。在生物信息学、医学、生态学等领域得到广泛应用。 本文将通过一个复杂热图的创建示例分享 ComplexHeatmap的语法规则。
1342 0