HDU-2222 Keywords Search 字符串问题 AC自动机
2024-10-01 14:21:25
题目链接:https://cn.vjudge.net/problem/HDU-2222
题意
给一些关键词,和一个待查询的字符串
问这个字符串里包含多少种关键词
思路
AC自动机模版题咯
注意一般情况不需要修改build方法,就像kmp里的getfail一样
一般的题目就是改改insert,query
一开始写的模版总是有问题,懒得改了
直接找的kuangbin的模版【原创】AC自动机小结
注意数组和指针的效率差不了多少,此题同一个算法的指针形式(296ms)比数组(187ms)慢110ms
说实在的,数组写法就是优雅。
网上那些指针的看着就难受,明明是好好的逻辑,变量名都是pqrvtxy,搞的跟被混淆了一样。
改了两套没一个舒服的,真难受。
提交过程
AC |
代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int ACSize=500000+20;
const int maxitem=26, maxn=1e4+20, maxword=50+20, maxl=1e6+20;
char word[maxword], line[maxl];
struct Trie{
int next[ACSize][26], fail[ACSize], cnt[ACSize];
int root, total;
int newnode(void){
for(int pos=0; pos<maxitem; pos++)
next[total][pos]=-1;
cnt[total]=0;
return total++;
}
void init(){
total=0;
root=newnode();
}
void insert(char buf[]){
int now=root;
for(int i=0; buf[i]; i++){
int pos=buf[i]-'a';
if(next[now][pos]==-1)
next[now][pos]=newnode();
now=next[now][pos];
}
cnt[now]++;
}
void build(void){
queue<int> que;
fail[root]=root;
for(int i=0; i<maxitem; i++)
if(next[root][i]==-1)
next[root][i]=root;
else{
fail[next[root][i]]=root;
que.push(next[root][i]);
}
while(!que.empty()){
int now=que.front(); que.pop();
for(int pos=0; pos<maxitem; pos++)
if(next[now][pos]==-1)
next[now][pos]=next[fail[now]][pos];
else{
fail[next[now][pos]]=next[fail[now]][pos];
que.push(next[now][pos]);
}
}
}
int query(char buf[]){
int now=root, res=0;
for(int i=0; buf[i]; i++){
int pos=buf[i]-'a';
now=next[now][pos];
for (int tmp=now; tmp!=root && cnt[tmp]!=-1; tmp=fail[tmp]){
res+=cnt[tmp];
cnt[tmp]=-1; // 注意此处,找到了就不要找第二次了,直接删除即可
}
}return res;
}
void debug(void){
for(int i=0; i<total; i++){
printf("id=%3d, fail=%3d, end=%3d [", i, fail[i], cnt[i]);
for(int j=0; j<maxitem; j++)
printf("%2d", next[i][j]);
printf("]\n");
}
}
}AC;
int main(void){
int T, n;
scanf("%d", &T);
while (T--){
AC.init();
scanf("%d", &n);
for (int i=0; i<n; i++){
scanf("%s", word);
AC.insert(word);
}AC.build();
scanf("%s", line);
printf("%d\n", AC.query(line));
}
return 0;
}
Time | Memory | Length | Lang | Submitted |
---|---|---|---|---|
187ms | 27744kB | 2369 | G++ | 2018-08-02 16:16:21 |
最新文章
- JBoss-7.1.1 http访问端口修改
- Winform 窗体控件随窗体自动(等比例)调整大小
- ie6下内容会撑开父级设置好的宽高
- Public and Private Interfaces in ruby
- K需要修改的内容
- linux基础命令学习(三)Vim使用
- 转载几篇关于GNU autotools的文章
- jQuery图片提示和文字提示
- Django学习系列之Form基础
- DevExpres表格控件运行时动态设置表格列
- JdbcTemplate 操作Oracle Blob
- SQL Server中日志
- [原创]Hadoop-2.5.2-HA原文译
- github上搜索资源
- NCE损失(Noise-Constrastive Estimation Loss)
- BZOJ1023:[SHOI2008]cactus仙人掌图(圆方树,DP,单调队列)
- LuoguP2161 [SHOI2009]会场预约
- iOS如何在iTunes网站查看并下载APP的dsym文件
- 正睿 2019 省选附加赛 Day1 T1 考考试
- openstack镜像制作思路、指导及问题总结
热门文章
- iOS开发-测量APP启动耗时
- Day 02 - 02 编程语言的分类
- failed to push some refs to &#39;git@github.com:RocsSun/mytest.git
- JS iframe给父类传值
- ElasticSearch启动报错,bootstrap checks failed
- IE9以下版本兼容h5标签
- C++ throw的实验 &; 异常类继承关系
- 为什么选性别会导致兴趣都选中-vue
- CF 567C(Geometric Progression-map)
- Button的Click事件与js函数的两种不同顺序触发方式