前置知识trie树,KMP算法
1.构建trie树
根据关键字构建trie树,需要标记当前字母是否为单词结尾
2.建立fail指针
与kmp相同,当当前位置不匹配时,循环找父节点的fail指针,直到该指针为根节点为止
若找到,则当前fail指针指向该指针的next[i]
若未找到,则当前指针fail指针指向根节点
3.在trie树上跑kmp
需要注意当前位置若匹配成功需要进行当前位置的fail指针的bfs,因为可能存在
h
she
这样某个模式串为另一模式串子串的情况,所以需要找到模式串中与当前位置匹配的串
HDOJ 2222
#include <cstdlib>
#include <cstdio>
#include <list>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX_STD 50+10
#define MAX_BUF 1000000+10
#define WORD 26
int t,n;
char tmp[MAX_STD],buf[MAX_BUF];
typedef struct node{
node* next[WORD];
node* fail;
int count;
node(){
memset(next,NULL,sizeof(next));
fail = NULL;
count = 0;
}
}node;
node* root;
void release_trie(node* c){
for(int i = 0;i < WORD;i++){
if(c->next[i]!=NULL){
release_trie(c->next[i]);
}
}
delete c;
}
void insert_word(){
int pos,len = strlen(tmp);
node* temp = root;
for(int i = 0;i < len;i++){
pos = tmp[i]-'a';
if(temp->next[pos] == NULL){
temp->next[pos] = new node();
}
temp = temp->next[pos];
}
temp->count++;
}
void build_fail(){
list<node*> s;
s.push_back(root);
node* head;
node* temp;
while(!s.empty()){
head = s.front();
s.pop_front();
for(int i = 0;i < WORD;i++){
if(head->next[i]!=NULL){
if(head == root){
head->next[i]->fail = root;
}else{
temp = head->fail;
while(temp != root){
if(temp->next[i] != NULL){
head->next[i]->fail = temp->next[i];
break;
}
temp = temp->fail;
}
if(temp == root){
if(root->next[i] != NULL){
head->next[i]->fail = root->next[i];
}else{
head->next[i]->fail = root;
}
}
}
s.push_back(head->next[i]);
}
}
}
}
int query()
{
int i = 0, cnt = 0, index = 0;
node *p = root;
node *temp;
while (buf[i]) {
index = buf[i] - 'a';
while (p->next[index]==NULL && p != root)p = p->fail;
if(p->next[index]!=NULL)p = p->next[index];
temp = p;
while (temp != root && temp->count != -1) {
cnt += temp->count;
temp->count = -1;
temp = temp->fail;
}
++i;
}
return cnt;
}
int main() {
scanf("%d",&t);
while(t--){
scanf("%d",&n);
root = new node();
root->fail = root;
while(n--){
scanf("%s",tmp);
insert_word();
}
build_fail();
scanf("%s",buf);
printf("%d\n",query());
release_trie(root);
}
return 0;
}