算法模板——AC自动机
时间:2022-05-07
本文章向大家介绍算法模板——AC自动机,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法、AC自动机详解。考虑到有时候字典会相当稀疏,所以引入了chi和bro指针进行优化——其原理比较类似于邻接表,这个东西和next数组本质上是一致的,只是chi和bro用于遍历某一节点下的子节点,next用于查询某节点下是否有需要的子节点)
1 type
2 point=^node;
3 node=record
4 ex:longint;st:ansistring;
5 ct:char;
6 fat,jump,chi,bro:point;
7 next:array['A'..'Z'] of point;
8 end;
9 var
10 i,j,k,l,m,n:longint;
11 head,p:point;
12 s1,s2:ansistring;
13 function getpoint:point;inline;
14 var p:point;c1:char;
15 begin
16 new(p);
17 p^.ex:=0;p^.st:='';
18 p^.ct:=chr(0);
19 p^.bro:=nil;p^.chi:=nil;
20 p^.fat:=nil;p^.jump:=head;
21 for c1:='A' to 'Z' do p^.next[c1]:=nil;
22 exit(p);
23 end;
24 procedure ins(s1:ansistring;x:longint);inline;
25 var p:point;s2:ansistring;i:longint;
26 begin
27 p:=head;S2:='';
28 for i:=1 to length(s1) do
29 begin
30 s2:=s2+s1[i];
31 if p^.next[s1[i]]=nil then
32 begin
33 p^.next[s1[i]]:=getpoint;
34 p^.next[s1[i]]^.fat:=p;
35 p^.next[s1[i]]^.st:=s2;
36 p^.next[s1[i]]^.ct:=s1[i];
37 p^.next[s1[i]]^.bro:=p^.chi;
38 p^.chi:=p^.next[s1[i]];
39 end;
40 p:=p^.next[s1[i]];
41 end;
42 if p^.ex=0 then p^.ex:=x;
43 end;
44 procedure linkit;inline;
45 var i,j,k,l,f,r:longint;
46 d:array[0..10000] of point;
47 p,p1,p2:point;
48 begin
49 f:=1;r:=2;d[1]:=head;
50 while f<r do
51 begin
52 p:=d[f]^.chi;
53 while p<>nil do
54 begin
55 d[r]:=p;
56 if d[f]<>head then
57 begin
58 p1:=d[f]^.jump;
59 while p1<>head do
60 begin
61 if p1^.next[p^.ct]<>nil then break;
62 p1:=p1^.jump;
63 end;
64 if p1^.next[p^.ct]<>nil then p^.jump:=p1^.next[p^.ct];
65 end;
66 inc(r);
67 p:=p^.bro;
68 end;
69 inc(f);
70 end;
71 end;
72 procedure fit(s1:ansistring);inline;
73 var p,p1:point;i:longint;
74 begin
75 p:=head;
76 for i:=1 to length(s1) do
77 begin
78 if p^.next[s1[i]]=nil then
79 begin
80 while (p^.next[s1[i]]=nil) and (p<>head) do p:=p^.jump;
81 if p^.next[s1[i]]<>nil then p:=p^.next[s1[i]];
82 end
83 else p:=p^.next[s1[i]];
84 p1:=p;
85 while p1<>head do
86 begin
87 if p1^.ex<>0 then writeln('No.',p1^.ex,' ',p1^.st,' From:',i-length(p1^.st)+1);
88 p1:=p1^.jump;
89 end;
90 end;
91 end;
92 begin
93 readln(n,m);
94 head:=getpoint;head^.jump:=head;
95 for i:=1 to n do
96 begin
97 readln(s1);
98 ins(upcase(s1),i);
99 end;
100 linkit;
101 for i:=1 to m do
102 begin
103 readln(s1);
104 fit(upcase(s1));
105 end;
106 end.
107
- 通往全栈工程师的捷径 —— React
- GLC - glog 日志清理类库
- Go发起Http请求及获取相关参数
- Go语言并发模型的2种编程方案
- 几种服务器端IO模型的简单介绍及实现(上)
- MySQL动态hash结构
- Golang不使用MD5比较文件内容是否一致
- go语言json操作指南
- 转-Golang自玩项目中一个重连机制实现.
- 当dex分包遇上NoClassDefFoundError & ClassNotFoundException
- go语言中的interface使用实例
- 内存泄露从入门到精通三部曲之基础知识篇
- NSQ的golang客户端简单使用
- Golang中channel使用的一些小技巧
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- idea--->先交给git本地仓库--->再push到远程仓库
- 图书系统优化分页与搜索跳转
- 解决ie浏览器回车不刷新验证码问题
- jsp跳转jsp----------和------------jsp跳转servlet跳转jsp
- idea中下载并配置稳定版本的MAVEN,电脑环境配置 + setting.xml文件配置
- Python代码性能分析之cProfile
- 自己写一个简单的MyBatis工具类代码+注释
- 多对一和一对多
- 使用C3P0连接数据库
- QQ授权,接收代码发送的电子邮件
- c:set
- 37道Python经典面试题(附答案),看完面试不愁了
- 错误提示合集--->待增加 Σ( ° △ °|||)︴
- RabbitMQ如何保证消息的可靠投递?
- Python处理json总结