之前写的,现在看不懂了。。。 还是要温故而知新呀! 本篇博客仅为了保留代码。
#ifndef _ACMATCH_H
#define _ACMATCH_H
#include<iostream>
#include <string.h>
#include <vector>
using namespace std;
// 用于标记在主串中的位置及长度
struct PosSet
{
std::vector<int> vPos;
std::vector<int> vLen;
};
// trie数结构
class ACNode
{
public:
// 允许用字符初始化变量
ACNode(const char ch):isEndingChar(false), length(-1), nodeNum(0), pFail(NULL)
{
data = ch;
memset(child, 0, sizeof(child));
}
// 默认构造函数,初始化变量
ACNode():isEndingChar(false), length(-1), nodeNum(0), pFail(NULL)
{
memset(child, 0, sizeof(child));
}
bool operator == (const ACNode &b)
{
return data == b.data;
}
~ACNode(){};
char data;
ACNode* child[26]; // 数组里面存储的是26个ACNode*
bool isEndingChar; // 是否为结尾字符
int length; // 当isEndingChar = true,记录模式串的长度
int nodeNum; // 记录结点个数
ACNode* pFail; // 失效结点
};
class AC
{
public:
AC(void);
~AC(void);
template<typename Iterator>
void insert(Iterator begin, Iterator end);
template<typename Iterator>
bool find(Iterator begin, Iterator end);
template<typename Iterator>
void match(Iterator begin, Iterator end, PosSet *ret);
void insert(const char* text);
bool find(const char* pattern);
void buildFailurePointer();
void match(const char* text, PosSet* ret);
void print(const char* text);
void clear();
private:
ACNode *root; // 模式串的根结点
void clear_node(ACNode cur);
};
#endif //_ACMATCH_H
#include "ACMatch.h"
#include <queue>
AC::AC(void)
{
root = new ACNode('/'); // 初始化根结点
}
AC::~AC(void)
{
clear();
}
/****************************************************************
* @brief : 插入模式串
* @author : dyx
* @date : 2019/8/26 19:20
* @version : ver 1.0
* @inparam :
* @outparam :
*****************************************************************/
template<typename Iterator>
void AC::insert(Iterator begin, Iterator end)
{
ACNode *cur = root;
int i;
for (i = 0; begin != end; ++begin, ++i)
{
int index = *begin - 'a';
if (cur->child[index] == 0) // 子结点为0,则进行新建结点
{
cur->child[index] = new ACNode(*begin);
++cur->nodeNum;
}
cur = cur->child[index]; // 子节点不为0,则继续找子节点的子节点
}
cur->isEndingChar = true;
cur->length = i; // 表示当前最后子节点的长度
};
void AC::insert(const char* text)
{
insert(text, text + strlen(text));
}
/****************************************************************
* @brief : 查找是否含有模式串
* @author : dyx
* @date : 2019/8/26 19:19
* @version : ver 1.0
* @inparam :
* @outparam :
*****************************************************************/
template<typename Iterator>
bool AC::find(Iterator begin, Iterator end)
{
ACNode* cur = root;
for (; begin != end; ++begin)
{
int index = *begin - 'a';
if (cur->child[index] == 0)
{
return false;
}
cur = cur->child[index];
}
return cur->isEndingChar;
}
bool AC::find(const char* pattern)
{
return find(pattern, pattern + strlen(pattern));
}
/****************************************************************
* @brief : 构建Trie树的失败指针,相当于KMP的next数组
* @author : dyx
* @date : 2019/8/26 19:00
* @version : ver 1.0
* @inparam :
* @outparam :
*****************************************************************/
void AC::buildFailurePointer()
{
queue<ACNode> que;
root->pFail = NULL;
que.push(*root);
while (!que.empty())
{
ACNode p = que.front();
que.pop();
for (int i = 0; i < 26; ++i)
{
ACNode *pc = p.child[i];
if (pc == NULL)
{
continue;
}
if (p == *root)
{
pc->pFail = root;
}
else
{
ACNode *q = p.pFail;
while (q != NULL)
{
ACNode *qc = q->child[pc->data - 'a'];
if (qc != NULL)
{
pc->pFail = qc;
break;
}
q = q->pFail;
}
if (q == NULL)
{
pc->pFail = root;
}
}
que.push(*pc);
}
}
}
/****************************************************************
* @brief : 匹配模式串
* @author : dyx
* @date : 2019/8/26 19:08
* @version : ver 1.0
* @inparam :
* @outparam :
*****************************************************************/
template<typename Iterator>
void AC::match(Iterator begin, Iterator end, PosSet *ret)
{
ACNode* cur = root;
for (int i = 0; begin != end; ++begin, ++i)
{
int index = *begin - 'a';
while(cur->child[index] == 0 && cur != root) // 没有孩子且不是根结点,就去找它的失效结点
{
cur = cur->pFail;
}
cur = cur->child[index];
if (cur == 0)
{
cur = root;
}
ACNode *pTemp = cur;
while(pTemp != root)
{
if (pTemp->isEndingChar == true)
{
ret->vPos.push_back(i - pTemp->length + 1);
ret->vLen.push_back(pTemp->length);
}
pTemp = pTemp->pFail;
}
}
}
/****************************************************************
* @brief : 匹配过程
* @author : dyx
* @date : 2019/8/26 19:13
* @version : ver 1.0
* @inparam : 字符串的首地址,
* @outparam : ret 保存 匹配到的字符串的位置和长度
*****************************************************************/
void AC::match(const char* text, PosSet* ret)
{
match(text, text + strlen(text), ret);
}
/****************************************************************
* @brief : 清空结点
* @author : dyx
* @date : 2019/8/26 19:14
* @version : ver 1.0
* @inparam :
* @outparam :
*****************************************************************/
void AC::clear_node(ACNode cur)
{
for(int i = 0; i < 26; ++i)
{
if (cur.child[i] == 0)
{
continue;
}
clear_node(*cur.child[i]);
delete cur.child[i];
cur.child[i] = 0;
if (--cur.nodeNum == 0) // 结点个数--
{
break;
}
}
}
/****************************************************************
* @brief : 清空all
* @author : dyx
* @date : 2019/8/26 19:15
* @version : ver 1.0
* @inparam :
* @outparam :
*****************************************************************/
void AC::clear()
{
clear_node(*root);
for (int i = 0; i < 26; ++i)
{
root->child[i] = 0;
}
}
/****************************************************************
* @brief : 打印输出。
* @author : dyx
* @date : 2019/8/26 19:15
* @version : ver 1.0
* @inparam : 主串
* @outparam : 如果含有模式串,则输出的主串会带**
*****************************************************************/
void AC::print(const char* text)
{
string str(text, text + strlen(text));
PosSet ret;
match(text, text + strlen(text), &ret);
for (size_t i = 0; i < ret.vPos.size(); ++i)
{
string stemp(ret.vLen[i], '*'); // *的长度
str = str.replace(ret.vPos[i], ret.vLen[i], stemp.c_str()); //起始位置,替换长度,替换内容
}
cout << str.c_str() << endl;
}
#include <iostream>
#include "ACMatch.h"
using namespace std;
int main()
{
AC ac;
// 插入一些模式串
ac.insert("hello");
ac.insert("world");
ac.insert("browse");
ac.insert("snake");
ac.insert("he");
ac.insert("her");
ac.insert("wor");
ac.insert("br");
// 建Trie树
ac.buildFailurePointer();
// 查找text中是否有模式串
if (ac.find("hello"))
{
cout << "FIND IT" << endl;
}
else
{
cout << "NOT FIND IT" << endl;
}
// 查找text中是否有模式串
if (ac.find("brother"))
{
cout << "FIND IT" << endl;
}
else
{
cout << "NOT FIND IT" << endl;
}
// 打印输出,且检查如果发现主串中含有模式串,则变为***
ac.print("hellowoldh");
ac.print("breosiof");
ac.print("hisd");
ac.print("her");
system("pause");
return 0;
}