hdu 1277 全文检索 (直接映射查找 || 自动机)
无聊做水题的时候发现的一道题目。这道题第一反应可以用自动机来解决。当然,条件是各种限制,从而导致可以用直接映射标记的方法来搜索。具体的做法就像RK算法一样,将字符串hash成一个数,这里每一个关键字前四位都是不同的,这样就有利于hash搜索了。当前四位匹配的时候,就可以搜索整个串是否完全匹配。这整个的复杂度大概是O(n*m),n是全文测长度,m是关键字的长度。
自动机代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <set> using namespace std; const int kind = ;
struct Node {
Node *next[kind];
Node *fail;
string label;
Node() {
memset(next, , sizeof(next));
fail = NULL;
label = "";
}
Node(char *tmp) {
memset(next, , sizeof(next));
fail = NULL;
label = tmp;
}
} ; struct Trie {
Node *Root;
Trie() { Root = new Node();} void insert(char *s, char *label) {
Node *p = Root;
while (*s) {
int idx = *s - '';
if (!p->next[idx]) {
p->next[idx] = new Node();
p->next[idx]->fail = p;
}
p = p->next[idx];
s++;
}
p->label = label;
}
void build() {
queue<Node *> Q;
while (!Q.empty()) Q.pop();
Q.push(Root);
Root->fail = NULL;
Node *cur, *p;
while (!Q.empty()) {
cur = Q.front();
Q.pop();
for (int i = ; i < kind; i++) {
// cout << cur->next[i] << ' ';
if (cur->next[i]) {
// cout << i << ' ';
Q.push(cur->next[i]);
p = cur->fail;
while (p) {
if (p->next[i]) {
cur->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if (!p) cur->next[i]->fail = Root;
}
}
}
}
void query(char *s) {
set<string> vis;
bool pnt = false;
Node *cur = Root;
while (*s) {
int idx = *(s++) - '';
while (cur && !cur->next[idx]) cur = cur->fail;
cur = cur ? cur->next[idx] : Root;
if (vis.find(cur->label) != vis.end()) continue;
if (cur->label.length()) {
if (!pnt) {
printf("Found key:");
pnt = true;
}
cout << ' ' << cur->label;
vis.insert(cur->label);
}
}
if (!pnt) puts("No key can be found !");
cout << endl;
}
} trie; char str[], buf[]; int main() {
// freopen("in", "r", stdin);
int n, m;
while (cin >> n >> m) {
trie = Trie();
gets(buf);
str[] = ;
while (n-- && gets(buf)) strcat(str, buf);
gets(buf);
while (m-- && gets(buf)) {
char *p = buf;
while (*(p++) != ']') ;
*(p++) = ;
while (*p == ' ') p++;
trie.insert(p, buf);
// cout << p << ' ' << buf << " inserted!"<< endl;
}
trie.build();
// cout << "built!!" << endl;
trie.query(str);
}
return ;
}
UPD:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string> using namespace std; const int HASHLEN = ;
const int M = ;
const int N = ;
string label[N], key[N];
bool vis[N];
int id[M];
char str[ * N], buf[N]; bool check(int t, char *p) {
int len = key[t].length();
for (int i = ; i < len; i++) {
if (key[t][i] != p[i]) return false;
}
return true;
} void work(char *p) {
bool pnt = false;
char *q = p;
int cur = , ep = ;
for (int i = ; i < HASHLEN - ; i++) cur = cur * + *(q++) - '', ep *= ;
while (*q && *p) {
// cout << cur << endl;
cur = cur * + *q - '';
cur %= ep;
int t = id[cur];
if (t != - && !vis[t]) {
if (check(t, p)) {
if (!pnt) printf("Found key:");
pnt = vis[t] = true;
cout << ' ' << label[t];
}
}
p++, q++;
}
if (!pnt) printf("No key can be found !");
cout << endl;
} int main() {
// freopen("in", "r", stdin);
int n, m;
while (cin >> n >> m) {
memset(id, -, sizeof(id));
memset(vis, , sizeof(vis));
gets(buf);
str[] = ;
while (n-- && gets(buf)) strcat(str, buf);
gets(buf);
for (int i = ; i < m; i++) {
gets(buf);
char *p = buf;
while (*p && *p != ']') p++;
*(++p) = ;
p++;
while (*p && *p == ' ') p++;
label[i] = buf;
key[i] = p;
// cout << label[i] << ' ' << key[i] << endl;
int cid = ;
for (int i = ; i < HASHLEN; i++) cid = cid * + p[i] - '';
// cout << cid << endl;
if (id[cid] != -) { puts("shit!"); while () ;}
id[cid] = i;
}
work(str);
}
return ;
}
不知道为什么这个代码能过G++但是C++过不了,应该是代码里面有bug。另外,数据似乎跟描述的有点出入,说好的不同key值的前四位不会相同,可是写了句来试它的数据时就发现被骗了,所以后来用了5位,过了!
——written by Lyon
hdu 1277 全文检索 (直接映射查找 || 自动机)的更多相关文章
- hdu 1277 全文检索
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1277 全文检索 Description 我们大家经常用google检索信息,但是检索信息的程序是很困难 ...
- HDU 1277全文检索(字典树)
全文检索 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- hdu 1277 全文检索 (字典树应用)
全文检索 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)
病毒侵袭 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- hdu 2896 病毒侵袭 ac自动机
/* hdu 2896 病毒侵袭 ac自动机 从题意得知,模式串中没有重复的串出现,所以结构体中可以将last[](后缀链接)数组去掉 last[]数组主要是记录具有相同后缀模式串的末尾节点编号 .本 ...
- hdu 1277 AC自动机入门(指针版和数组版)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1277 推荐一篇博客(看思路就可以,实现用的是java): https://www.cnblogs.co ...
- hdu 1277 AC自动机
全文检索 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 5164Matching on Array(AC自动机)
这是BC上的一道题,当时比赛没有做,回头看看题解,说是AC自动机,想着没有写过AC自动机,于是便试着抄抄白书的模板,硬是搞了我数个小时2000ms时限1800过了= = ! 这里就直接贴上BC的结题报 ...
- hdu 2222 Keywords Search ac自动机入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...
随机推荐
- Python实例 类和继承
class Base: def __init__(self): self.data = [] def add(self, x): self.data.a ...
- MaxCompute Spark开发指南
0. 概述 本文档面向需要使用MaxCompute Spark进行开发的用户使用.本指南主要适用于具备有Spark开发经验的开发人员. MaxCompute Spark是MaxCompute提供的兼容 ...
- HDU 1724 自适应辛普森法
//很裸的积分题,直接上模板 #include<stdio.h> #include<math.h> int aa, bb; //函数 double F(double x){ - ...
- hdu 1045 Fire Net(二分匹配 or 暴搜)
Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- System.ArgumentException: 回发或回调参数无效。在配置中使用 < pages enableEventValidation="true"/>
转载自http://blog.csdn.net/dongge825/article/details/7868151 关于在同一个页面中使用Gridview控件的时候发现气updaeting事件无法被服 ...
- Katalon系列二十一:用例中语句失败处理
假如有一个用例:1.登陆2.下单3.对历史单评价4.退出 情况一:当第1步执行失败时,我们希望用例不再执行,因为再执行也没有意义了,反而浪费时间:情况二:当第2步执行失败时,我们希望能略过第2步操作, ...
- iOS音频篇:使用AVPlayer播放网络音乐
http://www.cocoachina.com/ios/20160324/15767.html 引言 假如你现在打算做一个类似百度音乐.豆瓣电台的在线音乐类APP,你会怎样做? 首先了解一下音频播 ...
- 【风马一族_SQL Server】
原文来自:http://www.cnblogs.com/sows/p/6097684.html (博客园的)风马一族 侵犯版本,后果自负 2016-11-24 14:25:45 命令行方式处理服务管 ...
- 通过DataWorks数据集成归档日志服务数据至MaxCompute进行离线分析
通过DataWorks归档日志服务数据至MaxCompute 官方指导文档:https://help.aliyun.com/document_detail/68322.html但是会遇到大家在分区上或 ...
- 登录注册beta版
注册 login_count = 0 username_inp = input('请输入用户名:') while login_count < 3: pwd_inp = input('请输入密码: ...