AC自动机
来源:互联网 发布:生产环境 调试java 编辑:程序博客网 时间:2024/05/29 08:16
/** * 定义Trie树中子节点的最大个数,26个英文字母 * */const int MAX_NUM=26;/** * 用于构造Fail指针的队列,队列元素为拥有三个数据域 * 的对象: * fail表示Fail指针 * Child数组表示26个子节点指针 * IsOver表示当前节点是否为一个单词的结束节点 * */struct Node { Node *fail; Node *Child[MAX_NUM]; int IsOver; Node() { fail=NULL; IsOver=0; for(int i=0;i<26;i++) Child[i]=NULL; }} *queue[1000];/** * pattern表示输入的单词 * target表示目标匹配文本 * */char pattern[100];char target[10000];/** * head表示队列queue中的头结点,新元素入队的位置 * tail表示队列queue中的尾节点,元素出队的位置 * */int head;int tail;/** * 首先利用pattern构建Trie树 * Trie树的根节点root是一个包含空字符的辅助节点; * pointer指针遍历遍历Trie树 * temp指针临时替换一个节点的26个子节点中的一个 * index指针索引一个pattern中的字符 * 如果有多个pattern字符串,则需要多次调用此方法 * */void ConstructTrieTree(char *pattern, Node *root) { Node *pointer=root; Node *temp; char *index=pattern; /** * 此处循环以需要插入Trie树的pattern字符串作为依据 * */ while(*index!='\0') { temp=pointer->Child[*index-'a']; /** * 如果某一个字符对应的指针为NULL,则创建对应的节点 * */ if(temp==NULL) temp=new Node(); pointer=temp; index++; } /** * 当index指针pattern末尾的时候循环结束; * 此时pointer指向pattern的最后一个字符所在的节点 * */ pointer->IsOver=1;}/** * 然后构造Fail指针: * 在Trie树上构建Fail指针的基本策略如同BFS遍历 * 初始化将root入队,然后进入循环,循环检查队列是否为空,如果非空,则 * 取出一个节点进行处理,并将该的所节点有子节点加入队列;如果队列为空, * 则算法结束; * 对节点进行处理就是寻找其Fail指针的指向位置 * 如果当前节点的字符为A,则跳转到当前节点的父节点的fail指针指向的节点 * 处,判断其儿子中是否有为A字符的节点,如果没有则继续按照其自身的fail * 指针指向的节点跳转,直到找到字符为A的节点或者到达root节点处 * */void ConstructFailPointer(Node *root, Node **queue) { /** * 初始化root节点的fail指针,并将其入队queue * */ head=0;tail=0; root->fail=NULL; queue[head++]=root; Node *temp; Node *index; while(head!=tail) { /** * 从队列末尾获取一个节点 * */ temp=queue[tail++]; index=NULL; for(int i=0;i<26;i++) { /** * 处理当前节点,遍历其Child指针数组 * */ if(temp->Child[i]!=NULL) { /** * 对于root节点的直接子节点而言,由于他们没有 * 任何前缀而言,所以其fail指针都指向root节点 * */ if(temp==root) temp->Child[i]->fail=root; else { index=temp->fail; while(index!=NULL) { /** * 循环访问当前节点的fail指针指向的节点 * 考察其子节点中的Child[i]是否存在,也就是 * 是否有相同的字符 * */ if(index->Child[i]!=NULL) { /** * Child[i]表示当前处理的字符子节点 * temp表示原始父亲节点 * index表示根据fail指针跳转的节点 * */ temp->Child[i]->fail=index->Child[i]; break; } index=index->fail; } /** * root节点的fail指针初始化为NULL * */ if(index==NULL) temp->Child[i]->fail=root; } /** * 将temp节点的子节点入队queue * */ queue[head++]=temp->Child[i]; } } }}/** * 最后正式施行字符串匹配操作: * 利用Trie树(已经将所有的Pattern串插入)与target文本串进行匹配,有两种情况: * 1. 如果某一个节点的Child[i]对应target的字符存在,则下到子节点 * 2. 如果某一个节点的所有子节点Child[i]都没有与target的字符匹配的,则使用fail跳转 * 匹配函数最终返回pattern数组中单词在target文本串中出现的个数 * */int MultiPatternSearch(Node *root, char *target) { char *index1=target; Node *index2=root; Node *temp; int i=0, count=0; while(index1[i]!='\0') { /** * 如果不能匹配则跳转到fail指针指向的节点 * */ while(index2->Child[index1[i]-'a']==NULL && index2!=root) index2=index2->fail; /** * 准备匹配下一个字符,但如果上述循环是因为后面一个条件结束,则index2 * 需要重新指向root * */ index2=index2->Child[index1[i]-'a']; if(index2==NULL) index2=root; temp=index2; while(temp!=root && temp->IsOver==1) { count++; /** * 如果Trie树中的一个pattern成功匹配,则需要 * 将其IsOver域设置成0,防止重复匹配; * 然后跳转到与其具有公共前缀的fail指针指向的节点 * 继续进行匹配 * */ temp->IsOver=0; temp=temp->fail; } i++; } return count;}
阅读全文
0 0
- AC自动机...
- AC自动机
- AC 自动机
- AC自动机
- AC自动机
- ac自动机
- ac自动机
- AC自动机
- AC自动机
- AC自动机
- AC自动机
- AC自动机
- AC 自动机
- ac自动机
- AC自动机
- AC自动机
- AC自动机
- AC自动机
- 网址收藏夹
- 切换出页面执行事件、切换到页面执行事件 、页面重新加载时执行事件
- 【洛谷】P1079 Vigenère 密码
- jquery获取选中单选按钮radio的值,监听type=radio的click事件
- Hive on tez的insert union 子目录的问题
- AC自动机
- WXSS
- TensorFlow常用函数
- 国家级期刊发表有哪些技巧
- 语义歧义消除
- Oracle单行字符函数
- pl/sql developer不需要选中,执行光标所在行
- ovs安装出现fakeroot权限不足问题
- ble之Transmit window offset and Transmit window size