AC算法

最近没有新的学习内容,上一篇AC算法,可直接使用,需要的小伙伴直接拷贝,改吧改吧就可以直接用了


#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <string>
#include <cstdio>
using namespace std;


#define AC_FAIL_STATE   -1
#define AC_UNDEF_FAIL   -1
#define AC_CONT_SIZE    256


struct  ac_transition
{
	char  condition;
	int   next;
};

enum FSAType
{
	FSA_NULL = 0,
	FSA_NFA,
	FSA_DFA
};


struct  ac_state_finder :
	public binary_function<ac_transition, char, bool>
{
	bool  operator() (const ac_transition& t, char c) const
	{
		return  (t.condition == c);
	}
};


vector<vector<ac_transition> >   goto_table;
vector<vector<string> >          output_table;
vector<int>                      fail_table;
FSAType  fsa_type = FSA_NULL;


int  ac_goto(int _state, char _cont);
int  ac_creat_goto_table(const vector<string>& _ptns);
int  ac_creat_fail_table();
int  ac_convert_to_DFA();
int  ac_print_goto_table();
int  ac_search(const string& _txt);


int main(int argc, char** argv)
{
	string s; int n;
	vector<string>  ptns;
	cout << "please input the size of vector" << endl;
	cin >> n;
	cout << "please input the elements of pair" << endl;
	while (n--)
	{
		cin >> s;
		ptns.push_back(s);
	}
	cout << "please input the txt" << endl;
	string txt;
	cin >> txt;
	cout << "search is :" << endl;
	ac_creat_goto_table(ptns);
	ac_creat_fail_table();
	// ac_print_goto_table();
	// ac_search(txt);

	ac_convert_to_DFA();
	//ac_print_goto_table();
	ac_search(txt);

	return 0;
}


int  ac_goto(int _state, char _cont)
{
	vector<ac_transition>::const_iterator ret =
		find_if(goto_table[_state].begin(), goto_table[_state].end(),
		bind2nd(ac_state_finder(), _cont));
	if (goto_table[_state].end() == ret)
	{
		if (0 == _state)
			return 0;
		else
			return AC_FAIL_STATE;
	}
	else
		return ret->next;
}


int  ac_creat_goto_table(const vector<string>& _ptns)
{
	int state = 0;
	int state_id = 0;

	ac_transition t;
	vector<ac_transition>  ts;
	vector<string>  ss;

	goto_table.push_back(ts);
	output_table.push_back(ss);
	state_id++;

	for (vector<string>::const_iterator i = _ptns.begin(); i != _ptns.end(); ++i)
	{
		state = 0;
		for (string::const_iterator j = i->begin(); j<i->end(); ++j)
		{
			int next_state = ac_goto(state, *j);
			if (0 == next_state || AC_FAIL_STATE == next_state)
			{
				t.condition = *j;
				t.next = state_id++;
				goto_table[state].push_back(t);

				goto_table.push_back(ts);
				output_table.push_back(ss);

				state = t.next;
			}
			else
				state = next_state;
		}
		output_table[state].push_back(*i);
	}

	return 0;
}


int  ac_creat_fail_table()
{
	if (goto_table.empty())
		return -1;

	fail_table.resize(goto_table.size());
	for (size_t i = 0; i<goto_table.size(); ++i)
		fail_table[i] = AC_UNDEF_FAIL;

	queue<int>  q;
	for (vector<ac_transition>::const_iterator i = goto_table[0].begin();
		i != goto_table[0].end(); ++i)
	{
		fail_table[i->next] = 0;
		q.push(i->next);
	}

	int  state;
	while (!q.empty())
	{
		state = q.front();  q.pop();

		for (vector<ac_transition>::const_iterator i = goto_table[state].begin();
			i != goto_table[state].end(); ++i)
		{
			if (AC_UNDEF_FAIL != fail_table[i->next])
				continue;

			q.push(i->next);

			int  prev_state = state, ret;
			do
			{
				prev_state = fail_table[prev_state];
				ret = ac_goto(prev_state, i->condition);
			} while (AC_FAIL_STATE == ret);

			fail_table[i->next] = ret;

			for (vector<string>::const_iterator j = output_table[ret].begin();
				j != output_table[ret].end(); ++j)
			{
				vector<string>::const_iterator sret =
					find(output_table[i->next].begin(), output_table[i->next].end(), *j);
				if (output_table[i->next].end() == sret)
					output_table[i->next].push_back(*j);
			}
		}
	}

	fsa_type = FSA_NFA;

	return 0;
}


int  ac_convert_to_DFA()
{
	if (fsa_type != FSA_NFA)
		return -1;

	if (goto_table.empty() || fail_table.empty())
		return -1;

	queue<int>  q;
	for (vector<ac_transition>::const_iterator i = goto_table[0].begin();
		i != goto_table[0].end(); ++i)
	{
		q.push(i->next);
	}

	int  state;
	while (!q.empty())
	{
		state = q.front();  q.pop();

		for (size_t c = 0; c<AC_CONT_SIZE; ++c)
		{
			int  next_state = ac_goto(state, c);
			if (next_state != AC_FAIL_STATE && next_state != 0)
				q.push(next_state);
			else
			{
				next_state = ac_goto(fail_table[state], c);
				if (next_state != AC_FAIL_STATE && next_state != 0)
				{
					ac_transition t;
					t.condition = c;
					t.next = next_state;
					goto_table[state].push_back(t);
				}
			}
		}
	}

	fail_table.clear();
	fsa_type = FSA_DFA;

	return 0;
}


void  OutputMatch(int _state, size_t _pos)
{
	for (vector<string>::const_iterator i = output_table[_state].begin();
		i != output_table[_state].end(); ++i)
	{
		printf("%d %s : %d\n", _state, i->c_str(), _pos - i->length());
	}
}

int  ac_search(const string& _txt)
{
	if (goto_table.empty() || FSA_NULL == fsa_type)
		return -1;

	int  state = 0;
	string::size_type i;
	for (i = 0; i<_txt.length(); ++i)
	{
		char c = _txt[i];
		if (output_table[state].size() > 0)
			OutputMatch(state, i);

		if (FSA_NFA == fsa_type)
		{
			while (AC_FAIL_STATE == ac_goto(state, c))
				state = fail_table[state];
			state = ac_goto(state, c);
		}
		else if (FSA_DFA == fsa_type)
		{
			state = ac_goto(state, c);
			if (AC_FAIL_STATE == state)
				state = 0;
		}
	}

	if (output_table[state].size() > 0)
		OutputMatch(state, i);

	return 0;
}


int  ac_print_goto_table()
{
	if (goto_table.empty())
		return -1;

	int  state_id = 0;
	for (vector<vector<ac_transition> >::const_iterator i = goto_table.begin();
		i != goto_table.end(); ++i, ++state_id)
	{
		printf("%d: ", state_id);

		if (FSA_NFA == fsa_type)
			printf("%d ", fail_table[state_id]);

		for (vector<ac_transition>::const_iterator j = i->begin();
			j != i->end(); ++j)
		{
			printf("%c->%d ", j->condition, j->next);
		}

		for (vector<string>::const_iterator j = output_table[state_id].begin();
			j != output_table[state_id].end(); ++j)
		{
			printf("(%s) ", j->c_str());
		}
		printf("\n");
	}
	printf("\n");

	return 0;
}

猜你喜欢

转载自blog.csdn.net/liyu123__/article/details/82898911
今日推荐