AC自动机-一般算法实现

文件目录:

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跳转。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值