HDU2222 AC自动机静态模板

本蒟蒻第一次做AC自动机好慌哦;

http://acm.hdu.edu.cn/showproblem.php?pid=2222

题目的意思不多说了,就是求目标串中有几个模式串。虽然很简单,但不过我还是做了很久。

关于AC自动机,有静态和动态模板两种,静态好像效率比较高,速度也较快(但为什么这道题动态快一点呢),动态好像内存需求有点大,但不过都是基于字典树,还是比较好写的。我觉得静态的比较好写,记起来也要简单一点。关于AC自动机,我是怎么会最简单的模板的呢?这个还是要依靠我们万能的网站B站了,我觉得B站上的算法讲得还是很不错的。

直接上代码吧:

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 26;
const int MAXN = 500000 + 10;
struct node
{
	int next[MAXN][N], fail[MAXN], endd[MAXN];
	int root, l;
	int newnode()
	{
		for (int i = 0; i < N; i++)
			next[l][i] = 0;
		endd[l] = fail[l++] = 0;
		return l - 1;
	}
	void init()
	{
		l = 0;
		root = newnode();
	}
	void Insert(char s[])
	{
		int len = strlen(s);
		int now = root;
		for (int i = 0; i < len; i++)
		{
			if (next[now][s[i] - 'a'] == 0)
				next[now][s[i] - 'a'] = newnode();
			now = next[now][s[i] - 'a'];
		}
		endd[now]++;
	}
	void build()
	{
		queuequ;
		int now = root;
		for (int i = 0; i < N; i++)
		{
			if (next[root][i])
				qu.push(next[root][i]);
		}
		while (!qu.empty())
		{
			now = qu.front();
			qu.pop();
			for (int i = 0; i < N; i++)
			{
				if (!next[now][i])
					next[now][i] = next[fail[now]][i];
				else
				{
					fail[next[now][i]] = next[fail[now]][i];
					qu.push(next[now][i]);
				}
			}
		}
	}
	int query(char s[])
	{
		int len = strlen(s);
		int now = root;
		int ret = 0;
		for (int i = 0; i < len; i++)
		{
			now = next[now][s[i] - 'a'];
			int tmp = now;
			while (tmp != root)
			{
				ret += endd[tmp];
				endd[tmp] = 0;
				tmp = fail[tmp];
			}
		}
		return ret;
	}
};
node Aho;
int T, n;
char buf[MAXN], str[MAXN * 2];
int main()
{
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d", &n);
		Aho.init();
		for (int i = 0; i < n; i++)
		{
			scanf("%s", buf);
			Aho.Insert(buf);
		}
		Aho.build();
		scanf("%s", str);
		int ans = Aho.query(str);
		printf("%d\n", ans);
	}
	return 0;
}

在贴上动态的吧

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 26;
const int MAXN = 500005;
struct node
{
    node* fail;
    node* next[N];
    int cnt;
    node()
    {
        fail = NULL;
        cnt = 0;
        memset(next, NULL, sizeof(next));
    }
}*q[500010];
char keyw[51];
char str[1000010];
int head, tail;
void Insert(char *str, node *root)
{
    node *p = root;
    int i = 0, index;
    while (str[i])
    {
        index = str[i] - 'a';
        if (p->next[index] == NULL)
            p->next[index] = new node();
        p = p->next[index];
        i++;
    }
    p->cnt++;
}
void build(node *root)
{
    root->fail = NULL;
    q[head++] = root;
    while (head!=tail)
    {
        node *tmp = q[tail++];
        node *p = NULL;
        for (int i = 0; i < 26; i++)
        {
            if (tmp->next[i] != NULL)
            {
                if (tmp == root)
                    tmp->next[i]->fail = root;
                else
                {
                    p = tmp->fail;
                    while (p != NULL)
                    {
                        if (p->next[i] != NULL)
                        {
                            tmp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if (p == NULL)
                        tmp->next[i]->fail = root;
                }
                q[head++] = tmp->next[i];
            }
        }
    }
}
int query(node *root)
{
    int i = 0, ans = 0, index, len = strlen(str);
    node *p = root;
    while (str[i])
    {
        index = str[i] - 'a';
        while (p->next[index] == NULL&&p != root)
            p = p->fail;
        p = p->next[index];
        if (p == NULL)
            p = root;
        node *temp = p;
        while (temp != root&&temp->cnt != -1)
        {
            ans += temp->cnt;
            temp->cnt = -1;
            temp = temp->fail;
        }
        i++;
    }
    return ans;
}
int main()
{
    int T ,n; scanf("%d", &T);
    while (T--)
    {
        node* root = new node();
        scanf("%d", &n);
        head = tail = 0;
        while (n--)
        {
            scanf("%s", keyw);
            Insert(keyw, root);
        }
        build(root);
        scanf("%s", str);
        int ans = query(root);
        printf("%d\n", ans);
    }
    return 0;
}

 

你可能感兴趣的:(ACM题解,字符串)