Keywords Search

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25356    Accepted Submission(s): 8280

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
1 5 she he say shr her yasherhs
 
Sample Output
3
text:100万长度,关键字1万,多个测试案例,用Trie匹配必定超时。Trie也可以多模式匹配,不多比AC自动机耗时太多。
Trie 超时代码:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <iomanip>
#include <cstdlib>
using namespace std;
const int INF=0x5fffffff;
const int MS=;
const double EXP=1e-; struct node
{
int have;//根据情况灵活变化
node * next[];
}nodes[MS*]; //注意这个大小 尽量大一点 node *root;
int cnt,ans; char text[MS*]; node * add_node(int c)
{
node *p=&nodes[c];
for(int i=;i<;i++)
p->next[i]=NULL;
p->have=;
return p;
} void insert(char *str)
{
node *p=root;
int len=strlen(str);
for(int i=;i<len;i++)
{
int id=str[i]-'a';
if(p->next[id]==NULL)
{
p->next[id]=add_node(cnt++);
}
p=p->next[id];
}
p->have++;
}
void search(char *str)
{
node *p=root;
int len=strlen(str);
for(int i=;i<len;i++)
{
int id=str[i]-'a';
p=p->next[id];
if(p==NULL)
return ;
if(p->have)
{
ans+=p->have;
p->have=;
}
}
} int main()
{
int n,i,T;
scanf("%d",&T);
while(T--)
{
cnt=;
ans=;
root=add_node(cnt++);
scanf("%d",&n);
for(i=;i<n;i++)
{
scanf("%s",text);
insert(text);
}
scanf("%s",text);
int len=strlen(text);
for(i=;i<len;i++)
{
search(text+i);
}
printf("%d\n",ans);
}
return ;
}

这题是AC自动机最经典的入门题。学会了kmp,Trie,就可以学习ac自动机了。

time : 280 ms

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <iomanip>
#include <cstdlib>
using namespace std;
const int INF=0x5fffffff;
const int MS=;
const double EXP=1e-;
// AC自动机 KMP TRIE
struct node
{
bool isbad;
node *pre;
node * next[];
int n;
}nodes[MS*]; //注意这个大小 个数*每个的长度就不会访问非法内存 node *root;
int cnt,ans; char text[MS*]; node * add_node(int c)
{
node *p=&nodes[c];
for(int i=;i<;i++)
p->next[i]=NULL;
p->isbad=false;
p->pre=NULL;
p->n=;
return p;
} void insert(char *str)
{
node *p=root;
int len=strlen(str);
for(int i=;i<len;i++)
{
int id=str[i]-'a';
if(p->next[id]==NULL)
{
p->next[id]=add_node(cnt++);
}
p=p->next[id];
}
p->isbad=true;
p->n++; //终止节点
} void build()
{ // 在trie树上加前缀指针
for(int i=;i<;i++)
nodes->next[i]=root;
nodes->pre=NULL;
root->pre=nodes;
deque<node *> dq;
dq.push_back(root);
while(!dq.empty())
{
node *proot=dq.front();
dq.pop_front();
for(int i=;i<;i++)
{
node *p=proot->next[i];
if(p!=NULL)
{
node *pre=proot->pre;
while(pre)
{
if(pre->next[i]!=NULL) //NULL==0
{
p->pre=pre->next[i];
if(p->pre->isbad)
p->isbad=true;
break;
}
else
pre=pre->pre;
}
dq.push_back(p);
}
}
}
} void search(char *str)
{ //返回值为true,说明包含模式串
node *p=root;
int len=strlen(str);
for(int i=;i<len;i++)
{
int id=str[i]-'a';
while(p!=root&&p->next[id]==NULL)
{
p=p->pre;
}
p=p->next[id];
if(p==NULL)
{
p=root;
}
node *tp=p;
while(tp!=root&&tp->n!=)
{
ans+=tp->n;
tp->n=;
tp=tp->pre;
} /*
while(1) 是否包含模式串
{
if(p->next[id])
{
p=p->next[id];
if(p->isbad)
return true;
break;
}
else
p=p->pre;
}
*/
} //return false;
} int main()
{
int n,T;
scanf("%d",&T);
while(T--)
{
cnt=;
ans=;
add_node(cnt++);
root=add_node(cnt++);
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%s",text);
insert(text);
}
build();
scanf("%s",text);
search(text);
printf("%d\n",ans);
}
return ;
}
/*
节点p的前缀指针定义为:指向树中出现
过的S的最长的后缀(不能等于S)。
如果p节点匹配失败,该节点对应c,就沿着它的父节点的前缀指针走,直到某节点,其儿子节点
对应的字母也为c,把p节点的前缀指针指向该儿子节点。如果走到了root都没有找到,就指向root
*/
 
 

Keywords Search的更多相关文章

  1. 【HDU2222】Keywords Search AC自动机

    [HDU2222]Keywords Search Problem Description In the modern time, Search engine came into the life of ...

  2. hdu2222 Keywords Search ac自动机

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 题目: Keywords Search Time Limit: 2000/1000 MS ...

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

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

  4. HDU2222 Keywords Search [AC自动机模板]

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

  5. C++之路进阶——hdu2222(Keywords Search)

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

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

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

  7. hdu----(2222)Keywords Search(ac自动机)

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

  8. hdu----(2222)Keywords Search(trie树)

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

  9. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

随机推荐

  1. <一道题>abc+cba=1333,求满足条件的abc的值,隐含条件a!=0,c!=0

    这类东西,无非就是穷举法.见下面代码: #include <stdio.h> #include <stdlib.h> /* *abc + cba = 1333 * *a = ? ...

  2. spring mvc中的valid

    当你希望在spring mvc中直接校验表单参数时,你可以采用如下操作: 声明Validator的方式: 1.为每一个Controller声明一个Validator @Controller publi ...

  3. hdu 1084 What Is Your Grade?

    http://acm.hdu.edu.cn/showproblem.php?pid=1084 What Is Your Grade? Time Limit: 2000/1000 MS (Java/Ot ...

  4. datagridview里面有combox避免双击两次的写法

    双击两次变成单击一次的写法: void dataGridView_CellEnter(object sender, DataGridViewCellEventArgs e) { //实现单击一次显示下 ...

  5. ajax提交后台自动反序列化成对象

    下面是ajax提交的方法,主要用到了$form.serializeArray()将表单序列化成json对象,然后用each处理一下,代码如下: var $form = $('<form>& ...

  6. (图解版)SQL Server数据库备份与还原

        本文介绍了SQL Server数据库备份的两种方式.一种是直接拷贝数据库中的文件mdf 和日志文件ldf,另一种是生成脚本语言. 第一种方式:     选中需要备份的数据库,将数据库从运行的数 ...

  7. hdoj 5288 OO’s Sequence

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288 //*************头文件区************* #include<ios ...

  8. C++STL学习笔记_(3)stack

    10.2.4stack容器 Stack简介 ²  stack是堆栈容器,是一种"先进后出"的容器. ²  stack是简单地装饰deque容器而成为另外的一种容器. ²  #inc ...

  9. android开发中关于VersionCode和VersionName

    Google为APK定义了两个关于版本属性:VersionCode和VersionName,他们有不同的用途. VersionCode:对消费者不可见,仅用于应用市场.程序内部识别版本,判断新旧等用途 ...

  10. Java数据类型简单认识

    Java是一种强类型编程语言,因而在声明变量的时候必须声明数据类型,java语言有基本数据类型和引用数据类型这两大数据类型,基本数据类型有8种分别是4种整型.2种浮点类型.1种用于Unicode表示字 ...