文件目录:
ac_auto.cc //自动机实现
ac_auto.h
fifo_queue.cc //先进先出队列
fifo_queue.h
Makefile
ac_auto.cc
/*************************************************************************
> File Name: ac_auto.cpp
> Author: chenweishao
> Mail: chenweishaowdm@163.com
> Created Time: 2015年05月06日 星期三 16时09分33秒
************************************************************************/
#include "ac_auto.h"
#include "fifo_queue.h"
using namespace std;
int get_charpos(char c);
char get_char_bypos(int across);
void show_ac_tree(struct ac_node_t *root);
bool create_next(struct ac_node_t *root);
bool make_child_next(struct ac_node_t *node, int childpos);
void show_ac_next(struct ac_node_t *root);
int main()
{
struct ac_node_t *root = NULL;
int count = 0;
int time = 0;
int i = 0;
char ch;
char a[2014] = {'\0'};
sprintf(a, "%s", "ababcdabd");
insert_modle_string(&root, a);
sprintf(a, "%s", "ababcdabas");
insert_modle_string(&root, a);
sprintf(a, "%s", "cda");
insert_modle_string(&root, a);
sprintf(a, "%s", "c");
insert_modle_string(&root, a);
create_next(root);
show_ac_next(root);
sprintf(a, "%s", "adfsdc");
if (ac_match(root, a, strlen(a))) {
printf("match\n");
}
else {
printf("not match\n");
}
return 0;
}
bool ac_match(struct ac_node_t *root, char *s, int len)
{
int i = 0;
int charpos;
struct ac_node_t *node = root;
for (i = 0; i < len; i++) {
charpos = get_charpos(*(s+i));
if (node->children == NULL || node->children[charpos] == NULL) {
node = node->next;
}
else {
node = node->children[charpos];
}
if (node->end) {
return true;
}
}
return false;
}
bool make_child_next(struct ac_node_t *node, int childpos)
{
struct ac_node_t *grant = node->next;
struct ac_node_t *child = node->children[childpos];
if (child == NULL) {
return true;
}
bool match = false;
while (grant->next != grant) {
if (grant->children != NULL && grant->children[childpos] != NULL) {
child->next = grant->children[childpos];
match = true;
break;
}
grant = grant->next;
}
if (!match) {
if (grant->children[childpos] != NULL) {
child->next = grant->children[childpos];
}
else {
child->next = grant;
}
}
return match;
}
bool create_next(struct ac_node_t *root)
{
int childpos;
struct ac_node_t *node;
struct queue_root *fifo_queue = fifo_queue_init(); //init fifo_queue
/* root->child->next = root */
root->next = root;
for (childpos = 0; childpos < CHILDREN_NUM; childpos++) {
if (root->children[childpos] != NULL) {
(root->children[childpos])->next = root;
fifo_queue_insert(fifo_queue, (void *)(root->children[childpos]));
}
}
void *data;
while ((data = fifo_queue_get(fifo_queue)) != NULL) {
node = (struct ac_node_t *)data;
for (childpos = 0; childpos < CHILDREN_NUM; childpos++) {
if (node->children == NULL)
continue;
if (node->children[childpos] != NULL) { //insert fifo_queue
fifo_queue_insert(fifo_queue, (void *)(node->children[childpos]));
make_child_next(node, childpos);
}
}
}
fifo_queue_destory(fifo_queue);
return true;
}
bool insert_modle_string(struct ac_node_t **root, char *s)
{
if (s == NULL) {
return false;
}
if (*root == NULL) {
*root = (struct ac_node_t *)malloc(sizeof(struct ac_node_t));
if (*root == NULL) {
exit(-1);
}
init_ac_node(*root, NULL);
}
struct ac_node_t *index = *root;
struct ac_node_t *parent = *root;
int i = 0;
char c = '\0';
int pos = 0;
int len = strlen(s);
for (i = 0; i < len; i++) {
c = *(s+i);
pos = get_charpos(c);
if (index->children == NULL) {
index->children = (struct ac_node_t **)
malloc(sizeof(struct ac_node_t **)*CHILDREN_NUM);
if (index->children == NULL) {
exit(-1);
}
memset(index->children, '\0', sizeof(struct ac_node_t**)*CHILDREN_NUM);
}
if (index->children[pos] == NULL) {
index->children[pos] = (struct ac_node_t *)malloc(sizeof(struct ac_node_t));
if (index->children[pos] == NULL) {
exit(-1);
}
init_ac_node(index->children[pos], parent);
index->children[pos]->c = c;
parent = index->children[pos];
}
index = index->children[pos];
}
if (len > 0) {
index->end = true;
printf("end:%c\n", index->c);
}
return true;
}
void show_ac_next(struct ac_node_t *root)
{
struct queue_root *fifo_queue = fifo_queue_init();
fifo_queue_insert(fifo_queue, (void *)(root));
void *data;
struct ac_node_t *node;
int childpos = 0;
while ((data = fifo_queue_get(fifo_queue)) != NULL) {
node = (struct ac_node_t *)data;
for (childpos = 0; childpos < CHILDREN_NUM; childpos++) {
if (node->children == NULL) {
continue;
}
if (node->children[childpos] != NULL) {
fifo_queue_insert(fifo_queue, (void *)(node->children[childpos]));
printf("node:%c next:%c\n",
node->children[childpos]->c,
((node->children[childpos])->next)->c);
if ((node->children[childpos])->next == root) {
printf("root\n");
}
if (node->children[childpos]->end) {
printf("node:%c end\n", node->children[childpos]->c);
}
}
}
}
fifo_queue_destory(fifo_queue);
}
void show_ac_tree(struct ac_node_t *root)
{
struct ac_node_t *index = root;
struct ac_node_t *child;
int i = 0;
while (index != NULL) {
for (i = 0; i < 256; i++) {
if (index->children == NULL) {
return;
}
child = index->children[i];
if (child != NULL) {
printf("%c", i);
break;
}
}
index = child;
}
}
void init_ac_node(struct ac_node_t *node, struct ac_node_t *parent)
{
node->parent = parent;
node->next = NULL;
node->children = NULL;
node->c = '\0';
node->end = false;
}
int get_charpos(char c)
{
int across;
across = c - '\0';
if (across < 0) {
across += 256;
}
if (across < 0) {
printf("special c:%c\n", c);
}
return across;
}
char get_char_bypos(int across)
{
char c;
if (across > 127) {
across -= 256;
}
if (across > 127 || across < -128) {
printf("special across:%d", across);
}
c = across + '\0';
return c;
}
ac_auto.h
/*************************************************************************
> File Name: ac_auto.h
> Author: chenweishao
> Mail: chenweishaowdm@163.com
> Created Time: 2015年05月06日 星期三 15时54分40秒
************************************************************************/
#ifndef _ac_auto_h_
#define _ac_auto_h_
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define CHILDREN_NUM 256
using namespace std;
struct ac_node_t{
struct ac_node_t *parent;
struct ac_node_t **children; //256
struct ac_node_t *next;
bool end;
char c;
};
bool insert_modle_string(struct ac_node_t **root, char *s);
void init_ac_node(struct ac_node_t *node, struct ac_node_t *parent);
bool ac_match(struct ac_node_t *root, char *s, int len);
#endif
fifo_queue.cc
/*************************************************************************
> File Name: fifo_queue.cc
> Author: chenweishao
> Mail: chenweishaowdm@163.com
> Created Time: 2015年05月21日 星期四 11时36分58秒
************************************************************************/
#include "fifo_queue.h"
#include <pthread.h>
#include <time.h>
#include <unistd.h>
using namespace std;
struct queue_root *fifo_queue_init()
{
struct queue_root *fifo_queue = NULL;
fifo_queue = (struct queue_root *)malloc(sizeof(struct queue_root));
if (fifo_queue == NULL) {
exit(-1);
}
memset(fifo_queue, '\0', sizeof(struct queue_root));
return fifo_queue;
}
void fifo_queue_insert(struct queue_root *fifo_queue, void *data)
{
struct queue_node_t *node =
(struct queue_node_t *)malloc(sizeof(struct queue_node_t));
if (node == NULL) {
exit(-1);
}
memset(node, '\0', sizeof(struct queue_node_t));
node->next = NULL;
node->data = data;
if (fifo_queue->len == 0) {
fifo_queue->head = fifo_queue->tail = node;
}
else {
fifo_queue->tail->next = node;
fifo_queue->tail = node;
}
fifo_queue->len++;
}
void *fifo_queue_get(struct queue_root *fifo_queue)
{
if (fifo_queue->len == 0) {
return NULL;
}
struct queue_node_t *node = fifo_queue->head;
fifo_queue->head = fifo_queue->head->next;
fifo_queue->len--;
void *data = node->data;
free(node);
return data;
}
void *fifo_queue_destory(struct queue_root *fifo_queue)
{
void *data = NULL;
while ((data = fifo_queue_get(fifo_queue)) != NULL) {
continue;
}
free(fifo_queue);
return data;
}
/*
int main()
{
struct queue_root *fifo_queue;
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
int i, j, k;
int loop_count = 100000;
for (k = 0; k < loop_count; k++) {
fifo_queue = fifo_queue_init();
for (j = 0; j < 500000; j++) {
for (i = 0; i < sizeof(a)/sizeof(int); i++) {
fifo_queue_insert(fifo_queue, (void *)(a+i));
}
}
void *data;
while ((data = fifo_queue_get(fifo_queue)) != NULL) {
printf("%d - ", *((int *)data));
}
printf("\n");
printf("round:%d\n", k);
fifo_queue_destory(fifo_queue);
sleep(1);
}
return 0;
}
*/
fifo_queue.h
/*************************************************************************
> File Name: fifo_queue.h
> Author: chenweishao
> Mail: chenweishaowdm@163.com
> Created Time: 2015年05月21日 星期四 11时37分07秒
************************************************************************/
#ifndef _fifo_queue_h_
#define _fifo_queue_h_
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
using namespace std;
struct queue_root {
struct queue_node_t *head;
struct queue_node_t *tail;
int len;
};
struct queue_node_t {
struct queue_node_t *next;
void *data;
};
struct queue_root *fifo_queue_init();
void fifo_queue_insert(struct queue_root *fifo_queue, void *data);
void *fifo_queue_get(struct queue_root *fifo_queue);
void *fifo_queue_destory(struct queue_root *fifo_queue);
#endif
makefile:
TARGET=main
FILES=ac_auto.cc ac_auto.h fifo_queue.cc fifo_queue.h
${TARGET}:${FILES}
g++ -g -o ${TARGET} ${FILES}
ac_auto.o:ac_auto.cc ac_auto.h
g++ -c ac_auto.cc
fifo_queue.o:fifo_queue.cc fifo_queue.h
g++ -c fifo_queue.cc
clean:
rm -f *.o
rm -f ${TARGET}
其实该自动机可以改进,现在每个节点只有一个next指针,如果不考虑内存消耗。可以为每一个失败情况做一个next。这样能够跳过一些不必要的next跳转。