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的文本串. ...
随机推荐
- redis jedis存储对象简单操作,map list 自定义对象
安装好redis,进行了基本的操作.包括对map list 和自定义对象的基本操作.笔记都在代码注释里,直接上代码. private Jedis jedis; @Before public void ...
- thinkcmf 导航高亮制作方法(适用于多级导航)(通用)
平时用thinkcmf网站开发经常需要导航点击之后高亮,就写了一些实现方法分享一下. 思路很简单,先获取当前页面的顶级栏目的地址,然后与导航中的地址比较,相同的就加上一个class,把下面函数理解了不 ...
- 洛谷 P1892 [BOI2003]团伙
题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友. 两个强盗是同一团伙的 ...
- Django项目:CRM(客户关系管理系统)--01--01PerfectCRM基本配置ADMIN01
一.CRM项目需求 二.CRM项目新建 PerfectCRM crm
- bzoj 2705 [SDOI2012]Longge的问题——欧拉函数大水题
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2705 撕逼题.不就是枚举gcd==d,求和phi[ n/d ]么. 然后预处理sqrt (n ...
- MS17-010远程溢出漏洞 - 永恒之蓝 [CVE-2017-0143]
MS17-010远程溢出漏洞(永恒之蓝) Ti:2019-12-25 By:Mirror王宇阳 MS17-010 CVE-2017-0143 MS17-010 CVE-2017-0144 MS17-0 ...
- IntelliJ IDEA 下的SVN使用(傻瓜式教学)(转)
第一步:下载svn的客户端,通俗一点来说就是小乌龟啦!去电脑管理的软件管理里面可以直接下载,方便迅速 下载之后直接安装就好了,但是要注意这里的这个文件也要安装上,默认是不安装的,如果不安装,svn中的 ...
- DirectX11笔记(九)--Direct3D渲染5--CONSTANT BUFFERS
原文:DirectX11笔记(九)--Direct3D渲染5--CONSTANT BUFFERS 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u0 ...
- vue 根据数组中某一项的值进行排序
一.前言 我在vue项目中遇到了一个表格排序的需求,根据某一项的值的大小从大到小调整数组顺序. 二.代码 表格大概是这个样子,样式和图片在代码中简化了. <table class="r ...
- jsp里更新Clob类型字段数据
ResultSet rs = null; Connection conn = new dbconn().getconnect(); Statement stmt = null; int news=0; ...