Problem - 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 全文检索 (直接映射查找 || 自动机)的更多相关文章

  1. hdu 1277 全文检索

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1277 全文检索 Description 我们大家经常用google检索信息,但是检索信息的程序是很困难 ...

  2. HDU 1277全文检索(字典树)

    全文检索 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  3. hdu 1277 全文检索 (字典树应用)

    全文检索 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  4. hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. hdu 2896 病毒侵袭 ac自动机

    /* hdu 2896 病毒侵袭 ac自动机 从题意得知,模式串中没有重复的串出现,所以结构体中可以将last[](后缀链接)数组去掉 last[]数组主要是记录具有相同后缀模式串的末尾节点编号 .本 ...

  6. hdu 1277 AC自动机入门(指针版和数组版)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1277 推荐一篇博客(看思路就可以,实现用的是java): https://www.cnblogs.co ...

  7. hdu 1277 AC自动机

    全文检索 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  8. HDU 5164Matching on Array(AC自动机)

    这是BC上的一道题,当时比赛没有做,回头看看题解,说是AC自动机,想着没有写过AC自动机,于是便试着抄抄白书的模板,硬是搞了我数个小时2000ms时限1800过了= = ! 这里就直接贴上BC的结题报 ...

  9. hdu 2222 Keywords Search ac自动机入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...

随机推荐

  1. JSP-request(httpServletRequest)

    HttpServletRequest 1 HttpServletRequest概述 2 request运行流程 3 通过抓包工具抓的http请求 4 请求行信息的相关方法 //1.获得请求方式 Str ...

  2. Zookeeper 扫盲

    Zookeeper 扫盲 :disappointed_relieved: 配置文件详解: tickTime:基本事件单元,以毫秒为单位,这个时间作为 Zookeeper 服务器之间或客户端之间维持心跳 ...

  3. Maven常用命令备忘

    1. 修改版本号 mvn versions:set -DnewVersion=1.0.1-SNAPSHOT 2. <relativePath>的默认值是../pom.xml,如果没有配置, ...

  4. simple 单例

    Message* Message::m_pInstance = ;//类外初始 Message::Message() { } Message::~Message() { ) { delete Inst ...

  5. POJ 1061 扩展欧几里得

    #include<stdio.h> #include<string.h> typedef long long ll; void gcd(ll a,ll b,ll& d, ...

  6. laravel-admin 安装(总结)

    https://www.jianshu.com/p/844b05e4c45a laravel-admin 是一个可以快速帮你构建后台管理的工具,它提供的页面组件和表单元素等功能,能帮助你使用很少的代码 ...

  7. CAS小总结

      11                 if (log.isTraceEnabled()) { 12                     log.trace ("Logout requ ...

  8. vue制作幻灯片-左右移动

    组件中: <template> <div class="slide-show" @mouseover="clearInv" @mouseout ...

  9. Android——内存管理基础

    内存收集概念 内存垃圾收集器(garbage collector) 概念:自定内存管理. 功能:分配内存.保证所有被引用的对象还在内存中.可以释放在运行的代码中不再引用的对象的内存. 垃圾收集器避免了 ...

  10. 在VMware安装Windows server 2003操作系统帮助文档

    在VMware上安装Windows server 2003操作系统,及VMware上三种网络连接模式(以VMware 10为例) 一.在Windows上安装VMware 10虚拟机软件 1.首先在Wi ...