Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 51758    Accepted Submission(s):
16671

Problem Description
In the modern time, Search engine came into the life of
everybody like Google, Baidu, etc.
Wiskey also wants to bring this feature to
his image retrieval system.
Every image have a long description, when users
type some keywords to find the image, the system will match the keywords with
description of image and show the image which the most keywords be
matched.
To simplify the problem, giving you a description of image, and some
keywords, you should tell me how many keywords will be match.
 
Input
First line will contain one integer means how many
cases will follow by.
Each case will contain two integers N means the number
of keywords and N keywords follow. (N <= 10000)
Each keyword will only
contains characters 'a'-'z', and the length will be not longer than 50.
The
last line is the description, and the length will be not longer than
1000000.
 
Output
Print how many keywords are contained in the
description.
 
Sample Input

she
he
say
shr
her
yasherhs
 
Sample Output

 
Author
Wiskey
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  2896 3065 2243 2825 3341 
(转自 http://acm.hdu.edu.cn/showproblem.php?pid=2222)

  先讲讲大意,就是给一大堆模板串,再给一串很长的文本串,求有几个模板串在这个文本串中出现过
  首先,模板串的长度较短,数量多,极其符合ac自动机的特点,就这么愉快地决定使用ac自动机(其实也并不是特别地愉快
,虽说是裸题)
  接着注意几个事项
  1.模板串重复出现,比如下面这组数据

aa
bb
aa
aabbcc

  2.多组数据,第一个输入的数是数据组数(这个问题应该不大)

  3.如果用数组的话不要一次性用memset把整个数组都赋值,这样的话是十分浪费时间的

接着附上用指针写的AC自动机(虽说我用数组写了一个,调试了2天都没有调出来,果断重写)

Code

 /*
* acm.hdu.edu.cn
* Problem#2222
* Accepted
* Time:296ms
* Memory:58152k
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define SEG_SIZE 26
typedef class TrieNode{
public:
TrieNode* next[SEG_SIZE];
TrieNode* fail; //失配指针
TrieNode* last; //后缀链接
int value;
TrieNode():fail(NULL),last(NULL),value(){
memset(next, , sizeof(next));
}
}TrieNode;
typedef class Trie {
public:
TrieNode* root;
Trie(){
root = new TrieNode();
}
static int cti(char ch){ //将字符转换成Trie树中next数组的下标
return ch - 'a';
}
void insert(string s){
TrieNode *p = root;
for(int i = ;i < s.length();i++){
int c = cti(s[i]);
if(p->next[c] == NULL){
TrieNode *newNode = new TrieNode();
p->next[c] = newNode; //链接结点
}
p = p->next[c];
}
p->value++; //用结点的特殊值来存储有多少个单词是在这结尾
}
}Trie;
typedef class AhoMachine{
public:
Trie trie;
int count;
AhoMachine(){
trie = Trie();
count = ;
}
void getFail(){
queue<TrieNode*> que; //以bfs序构造状态转移图
trie.root->fail = trie.root;
for(int i = ;i < SEG_SIZE;i++){
TrieNode* pNode = trie.root->next[i];
if(pNode != NULL){
que.push(pNode);
pNode->fail = trie.root; //根节点的直接子节点的失配指针都是指向根节点
}
}
while(!que.empty()){
TrieNode* p = que.front();
que.pop();
for(int i = ;i < SEG_SIZE;i++){
TrieNode* pNode = p->next[i];
if(pNode == NULL) continue;
que.push(pNode);
TrieNode* pFail = p->fail;
//直到匹配,或者已经指向了根节点
while(pFail != trie.root && pFail->next[i] == NULL) pFail = pFail->fail;
pNode->fail = pFail->next[i];
if(pNode->fail == NULL) pNode->fail = trie.root;
//后缀链接的链接,指向失配后的结点或失配后的结点的后缀链接
pNode->last = (pNode->fail->value != )?(pNode->fail):(pNode->fail->last);
}
}
}
//当匹配完,或者是在一条链的中途仍然可能存在有匹配的结点
void rfind(TrieNode *p){
if(p != NULL){
count += p->value;
rfind(p->last);
p->value = ;
}
}
void find(string s){
TrieNode *pNode = trie.root;
for(int i = ;i < s.length();i++){
int c = Trie::cti(s[i]);
while(pNode != trie.root && pNode->next[c] == NULL) pNode = pNode->fail;
pNode = pNode->next[c];
if(pNode == NULL) pNode = trie.root;
if(pNode->value != ) rfind(pNode); //判断有没有可能匹配完其它的模板
else if(pNode->last != NULL) rfind(pNode->last);
}
}
}AC;
AC *ac;
int cases;
string buf;
int n;
int main(){
ios::sync_with_stdio(false); //取消同步,加快cin读取字符串的速度
cin>>cases;
while(cases--){
ac = new AC();
cin>>n;
for(int i = ;i < n;i++){
cin>>buf;
ac->trie.insert(buf);
}
cin>>buf;
ac->getFail();
ac->find(buf);
cout<<ac->count<<endl;
delete ac;
}
return ;
}

[后记]
  附上自己调程序时所用的数据生成器,如果用随机数生成可能基本上刷个1000,2000组很多问题都不能找出来,
因为直接用随机数要刷出点神数据的概率还是比较低的
 #include<iostream>
#include<fstream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<sstream>
using namespace std;
ofstream fout("ks.in");
//测试数据最少组数
#define CASE_LOW 3
//测试数据最大生成组数(CASE_LOW + CASE_LIMIT - 1)
#define CASE_LIMIT 10
//关键字最小生成组数
#define KEYWORD_LOW 3
#define KEYWORD_LIMIT 10
#define KEYWORD_MAX_LEN 5
//生成文章的次数
#define STR_TIMES 10
#define SUBSTR_LEN 5
string buf[KEYWORD_LIMIT + KEYWORD_LOW];
string str;
int _count;
string operator +(string str, char c){
stringstream ss;
ss<<str<<c;
return ss.str();
}
int main(){ srand((unsigned)time(NULL)); int cases = rand()%CASE_LIMIT + CASE_LOW;
fout<<cases<<endl; for(int i = ;i < cases;i++){ _count = rand()%KEYWORD_LIMIT + KEYWORD_LOW;
fout<<_count<<endl;
for(int j = ; j <= _count;j++){
int len = rand()%KEYWORD_MAX_LEN + ;
buf[j] = "";
for(int k = ; k <= len;k++){
buf[j] = buf[j] + (char)(rand()% + 'a');
}
fout<<buf[j]<<endl;
} int times = rand()%STR_TIMES + ;
str = "";
for(int j = ;j <= times;j++){ int v = rand()%;
if(v == ){
str += buf[rand()%_count + ];
}else{
int len = rand()%SUBSTR_LEN + ;
for(int i = ;i <= len;i++){
str = str + (char)(rand()% + 'a');
}
} } fout<<str<<endl; } fout.close();
return ;
}

md_ks.cpp

hdu 2222 Keywords Search - Aho-Corasick自动机的更多相关文章

  1. HDU 2222 Keywords Search(AC自动机模版题)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  2. HDU 2222 Keywords Search(AC自动机模板题)

    http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:给出多个单词,最后再给出一个模式串,求在该模式串中包含了多少个单词. 思路: AC自动机的模板题. ...

  3. HDU 2222 Keywords Search 【AC自动机】

    题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=2222] 题意:给出很多小字符串,然后给出一个文本串,问文本串中包含多少个小字符串.也就是说如果文本串 ...

  4. HDU 2222 Keywords Search (AC自动机)

    题意:给你一些模式串,再给你一串匹配串,问你在匹配串中出现了多少种模式串,模式串可以相同 AC自动机:trie树上进行KMP.首先模式串建立trie树,再求得失配指针(类似next数组),其作用就是在 ...

  5. HDU 2222 Keywords Search(AC自动机入门)

    题意:给出若干个单词和一段文本,问有多少个单词出现在其中.如果两个单词是相同的,得算两个单词的贡献. 分析:直接就是AC自动机的模板了. 具体见代码: #include <stdio.h> ...

  6. HDU 2222 Keywords Search(AC自动机)题解

    题意:给你几个keywords,再给你一段文章,问你keywords出现了几次. 思路:这里就要用到多模匹配算法AC自动机了,AC自动机需要KMP和字典树的知识,匹配时是在字典树上,失配我们就要用到类 ...

  7. HDU 2222 Keywords Search 【AC自动机模板】

    询问有多少个模式串出现在了文本串里面.将模式串插入Trie树中,然后跑一边AC自动机统计一下就哦了. 献上一份模板. #include <cstdio> #include <cstr ...

  8. hdu 2222 Keywords Search(AC自动机)

    /* 啥也不说了,直接套模板... */ 1 #include<iostream> #include<map> #include<string> #include& ...

  9. HDU 2222 Keywords Search(查询关键字)

    HDU 2222 Keywords Search(查询关键字) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K ...

  10. hdu 2222 Keywords Search

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:裸AC自动机,直接贴代码做模板 #include<stdio.h> #includ ...

随机推荐

  1. InfluxDB通过HTTP API

    SELECT "value" FROM "online_user_counter" curl -POST http://localhost:8086/query ...

  2. iOS多线程编程之GCD的常见用法(转载)

    一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) withObject:nil aft ...

  3. 交换机-查看mac地址表

    1.使用交换机命令行 en  或者  enable   进入特权模式 Switch> Switch>en Switch# Switch# 2.查看交换机中的MAC地址表 Switch#sh ...

  4. OLTP与OLAP

    当今的数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing).联机分析处理OLAP(On-Line Analytical Processing ...

  5. js与jQuery差别

    jQuery能大大简化Javascript程序的编写,我近期花时间了解了一下jQuery.把我上手过程中的笔记和大家分享出来.希望对大家有所帮助. 要使用jQuery.首先要在HTML代码最前面加上对 ...

  6. android返回到第一个activity

    问题:Android顺序打开多个Activity,如何返回到第一个Activity(一般为首页)? 情形:如 A 打开 B, B 打开 C, C 打开 D, 然后如果从 D 一步返回到 A,并清楚掉 ...

  7. iota 币产生私钥的方法

    iota 币的官网是 iota.org,   iota 的官网推荐的钱包地址是: https://github.com/iotaledger/wallet    iota 币产生私钥是没有什么特殊的要 ...

  8. 【Cocos2dx 3.3 Lua】触屏事件

    cocos2dx 3.x触屏时间分为单点触摸和多点触摸:     单点触摸:(即只有注册的Layer才能接收触摸事件)      多点触摸点单用法(多个Layer获取屏幕事件):           ...

  9. 轮廓的查找、表达、绘制、特性及匹配(How to Use Contour? Find, Component, Construct, Features & Match)

    http://www.cnblogs.com/xrwang/archive/2010/02/09/HowToUseContour.html 作者:王先荣 前言    轮廓是构成任何一个形状的边界或外形 ...

  10. VB.net 与线程

    Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1 ...