注:由于代码中使用了,对象初始化,所以编译的时候必须使用g++,但是可以修改掉C++内容,编程纯c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
const int MAXQ = 500000+10;
const int MAXN = 1000000+10;
const int MAXK = 26; //自动机里字符集的大小
struct TrieNode
{
struct TrieNode* fail;
struct TrieNode* next[MAXK];
bool danger; //该节点是否为某模式串的终结点
int cnt; //以该节点为终结点的模式串个数
TrieNode()
{
fail = NULL;
memset(next, 0, sizeof(next));
danger = false;
cnt = 0;
}
}*que[MAXQ], *root;
//文本字符串
char msg[MAXN];
int N;
void TrieInsert(char *s)
{/*建立goto表*/
int i = 0;
TrieNode *ptr = root;
while(s[i])
{
int idx = s[i]-'a';
if(ptr->next[idx] == NULL)
ptr->next[idx] = new TrieNode();
ptr = ptr->next[idx];
i++;
}
ptr->danger = true;
ptr->cnt++;
}
void Init()
{
int i;
char s[100];
char a1[10]="she";
char a2[10]="his";
char a3[10]="hers";
char a4[10]="he";
root = new TrieNode();
//scanf("输入待匹配的字符串个数:%d", &N);
//for(i = 0; i < 4; i++)
//{
//scanf("输入第%d个带匹配字符串%s",i, s);
TrieInsert(a1);
TrieInsert(a2);
TrieInsert(a3);
TrieInsert(a4);
//}
}
void Build_AC_Automation()
{
int rear = 1, front = 0, i;
que[0] = root;
root->fail = NULL;
while(rear != front)
{
TrieNode *cur = que[front++];
for(i = 0; i < 26; i++)
if(cur->next[i] != NULL)
{
if(cur == root)
cur->next[i]->fail = root;
else
{
TrieNode *ptr = cur->fail;
while(ptr != NULL)
{
if(ptr->next[i] != NULL)
{/*建立fail表,所有新单词从第一个字母开始建立,无匹配则跳转到开始节点,
下一个则从上一个字母的fail表匹配,如此则避免了重新划分最长后缀--空间换时间*/
cur->next[i]->fail = ptr->next[i];
if(ptr->next[i]->danger == true)
cur->next[i]->danger = true;
break;
}
ptr = ptr->fail;
}
if(ptr == NULL) cur->next[i]->fail = root;
}
que[rear++] = cur->next[i];
}
}
}
int AC_Search()
{
int i = 0, ans = 0;
TrieNode *ptr = root;
while(msg[i])
{
int idx = msg[i]-'a';
while(ptr->next[idx] == NULL && ptr != root) ptr = ptr->fail;
ptr = ptr->next[idx];
if(ptr == NULL) ptr = root;/*非终点字符串,有未匹配的时候,直接跳转到起点重新匹配*/
TrieNode *tmp = ptr;
while(tmp != NULL && tmp->cnt != -1)
{
ans += tmp->cnt;/*这里只计算第一次命中某字段*/
tmp->cnt = -1;/*已经命中过的字符串,所有output表全部清空*/
tmp = tmp->fail;/*终点字符串直接查找跳转表*/
}
i++;
}
return ans;
}
int main()
{
int T = 2;
// scanf("输入待检查的字符串个数:%d", &T);
while(T--)
{
Init();
Build_AC_Automation();
//文本
//scanf("输入待检查的字符串:%s", msg);
strcpy(msg,"i am shenjinwei,he not hers, is a man");
printf("总共有%d个字符串可以匹配上\n", AC_Search());
}
return 0;
}
ac算法--c++实现
最新推荐文章于 2024-12-03 15:15:25 发布