自己主动机串标: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
版权声明:本文博客原创文章,博客,未经同意,不得转载。
自己主动机串标:Directed Acyclic Word Graph的更多相关文章
- [POJ 1204]Word Puzzles(Trie树暴搜&AC自己主动机)
Description Word puzzles are usually simple and very entertaining for all ages. They are so entertai ...
- HDOJ 5421 Victor and String 回文串自己主动机
假设没有操作1,就是裸的回文串自己主动机...... 能够从头部插入字符的回文串自己主动机,维护两个last点就好了..... 当整个串都是回文串的时候把两个last统一一下 Victor and S ...
- hdoj 2222 Keywords Search 【AC自己主动机 入门题】 【求目标串中出现了几个模式串】
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- hdu5384 AC自己主动机模板题,统计模式串在给定串中出现的个数
http://acm.hdu.edu.cn/showproblem.php?pid=5384 Problem Description Danganronpa is a video game franc ...
- Hdu 3341 Lost's revenge (ac+自己主动机dp+hash)
标题效果: 举个很多种DNA弦,每个字符串值值至1.最后,一个长字符串.要安排你最后一次另一个字符串,使其没事子值和最大. IDEAS: 首先easy我们的想法是想搜索的!管她3721..直接一个字符 ...
- Hdu 3962 Microgene (AC自己主动机+矩阵)
标题效果: 构造一个字符串,使得有两个和两个以上的目标串.长短L这一系列有多少串都. IDEAS: 只有全款减有1一些字符串,没有目标就是答案. 假定数据是非常小的,够用dp解.dp[i][j][k] ...
- Codeforces 86C Genetic engineering (AC自己主动机+dp)
题目大意: 要求构造一个串,使得这个串是由所给的串相连接构成,连接能够有重叠的部分. 思路分析: 首先用所给的串建立自己主动机,每一个单词节点记录当前节点可以达到的最长后缀. 開始的时候想的是dp[i ...
- Hdu 2457 DNA repair (ac自己主动机+dp)
题目大意: 改动文本串的上的字符,使之不出现上面出现的串.问最少改动多少个. 思路分析: dp[i][j]表示如今 i 个字符改变成了字典树上的 j 节点. 然后顺着自己主动机一直转移方程. 注意合法 ...
- 字符串算法之 AC自己主动机
近期一直在学习字符串之类的算法,感觉BF算法,尽管非常easy理解,可是easy超时,全部就想学习其它的一些字符串算法来提高一下,近期学习了一下AC自己主动机.尽管感觉有所收获,可是还是有些朦胧的感觉 ...
随机推荐
- 收集经常使用的.net开源项目
Json.NET http://json.codeplex.com/ Json.Net是一个读写Json效率比較高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过Lin ...
- POJ 2948 DP
一个row*col的矩阵,每一个格子内有两种矿yeyenum和bloggium,而且知道它们在每一个格子内的数量是多少.最北边有bloggium的收集站,最西边有 yeyenum 的收集站.如今要在这 ...
- Axure RP 实践.1
工作需要设计产品原型,找来Axure RP帮忙,看了一些文章,其中下面这段话深得我心. “只使用Axure的默认控件(Wireframe),不要用那些样式花哨的自定义控件,并且所有页面中使用的颜色不能 ...
- ubuntu Linux 安装和首次使用
1.ubuntu Linux 安装后切换到root账户,在默认情况下,系统安装过程中需要创建一个用户,切换到root账号命令如下:$ sudo -s -H输入 当前账户密码就可以切换到root.2.u ...
- Berkeley DB 使用
http://www.ibm.com/developerworks/cn/linux/l-embdb/index.html UNIX/LINUX平台下的数据库种类非常多,参考资料1中 列举了其中的大部 ...
- python基础课程_2学习笔记3:图形用户界面
图形用户界面 丰富的平台 写作Python GUI程序前,须要决定使用哪个GUI平台. 简单来说,平台是图形组件的一个特定集合.能够通过叫做GUI工具包的给定Python模块进行訪问. 工具包 描写叙 ...
- JVM指令集(指令码、助记符、功能描述)(转)
JVM指令集(指令码.助记符.功能描述) 指令码 助记符 功能描述 0x00 nop 无操作 0x01 aconst_null 指令格式: aconst_null 功能描述: null进栈. 指令 ...
- java性能缓慢
虚拟帝国上面有很多营销软件是JAVA开发的!创业公司通常选择开源技术减少项目管理费用. 除了使用Java编程语言,创业公司也可以利用Java开发工具包的好处(JDK),Java运行时环境(JRE)和J ...
- EF 批量 循环删除
var list = db.T_xAppRecord.Where(u => u.Id == 1).ToList(); //2.0 遍历集合,将 要删除的 对象 的代理对象的State 设置为 D ...
- 划分树 静态第k大
划分树是保存了快速排序的过程的树,可以用来求静态第k小的数 如果,划分树可以看做是线段树,它的左孩子保存了mid-L+1 个 小于等于 a[mid] 的数字, 右孩子保存了 R-mid个大于等于a[ ...