zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    在IE浏览器中url传参长度问题
    Linq语句的认识
    关于选择表达式以及判断语句的书写,可以让代码更加的清晰。
    C#/对线程的认识
    Js/如何修改easyui修饰的input的val值
    Java Lambda表达式中的this
    MySQL USING关键词/USING()函数的使用
    复杂SQL查询
    Java 修饰符
    Git:idea中将当前分支修改的内容提交到其他分支上
  • 原文地址:https://www.cnblogs.com/Przz/p/5409844.html
Copyright © 2011-2022 走看看