• HDU2222 自动机(学习中)


    题目大意:

    给你很多个单词,然后给你一篇文章,问给出的单词在文章中出现的次数。

    解题思路:

    AC自动机入门题。需要注意的就是可能有重复单词

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    using namespace std;
    #define N 500010
    char str[1000010], keyword[51];
    int head, tail;
    
    struct node
    {
    	node *fail;
    	node *next[26];
    	int count;
    	node() //init
    	{
    		fail = NULL;
    		count = 0;
    		for(int i = 0; i < 26; ++i)
    			next[i] = NULL;
    	}
    }*q[N];
    node *root;
    
    void insert(char *str) //建立Trie
    {
    	int temp, len;
    	node *p = root;
    	len = strlen(str);
    	for(int i = 0; i < len; ++i)
    	{
    		temp = str[i] - 'a';
    		if(p->next[temp] == NULL)
    			p->next[temp] = new node();
    		p = p->next[temp];
    	}
    	p->count++;
    }
    
    void build_ac() //初始化fail指针,BFS
    {
    	q[tail++] = root;
    	while(head != tail)
    	{
    		node *p = q[head++]; //弹出队头
    		node *temp = NULL;
    		for(int i = 0; i < 26; ++i)
    		{
    			if(p->next[i] != NULL)
    			{
    				if(p == root) //第一个元素fail必指向根
    					p->next[i]->fail = root;
    				else
    				{
    					temp = p->fail; //失败指针
    					while(temp != NULL) //2种情况结束:匹配为空or找到匹配
    					{
    						if(temp->next[i] != NULL) //找到匹配
    						{
    							p->next[i]->fail = temp->next[i];
    							break;
    						}
    						temp = temp->fail;
    					}
    					if(temp == NULL) //为空则从头匹配
    						p->next[i]->fail = root;
    				}
    				q[tail++] = p->next[i]; //入队
    			}
    		}
    	}
    }
    
    int query() //扫描
    {
    	int index, len, result;
    	node *p = root; //Tire入口
    	result = 0;
    	len = strlen(str);
    	for(int i = 0; i < len; ++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; //p不动,temp计算后缀串
    		while(temp != root && temp->count != -1)
    		{
    			result += temp->count;
    			temp->count = -1;
    			temp = temp->fail;
    		}
    	}
    	return result;
    }
    
    int main()
    {
    	int ncase, num;
    	scanf("%d", &ncase);
    	while(ncase--)
    	{
    		head= tail = 0;
    		root = new node();
    		scanf("%d", &num);
    		getchar();
    		for(int i = 0; i < num; ++i)
    		{
    			gets(keyword);
    			insert(keyword);
    		}
    		build_ac();
    		scanf("%s", str);
    		printf("%d
    ", query());
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    串的动态存储分配
    队列的链式表示
    堆栈相关知识
    函数参数的传值与传址
    js原生实现getElementsByClassName
    js原生复杂实现animate操作Css3属性(升级版!)
    在 CentOS 6 上安装 PHP 5.4.30
    CentOS 更改MySQL数据库目录位置
    使用X-UA-Compatible来设置IE浏览器兼容模式.
    __set() And __get() 使用详解.
  • 原文地址:https://www.cnblogs.com/Przz/p/5409844.html
Copyright © 2020-2023  润新知