Keywords Search HDU - 2222(ac自动机板题。。)
求一个字符串上有多少个匹配的单词
看着卿学姐的板子写的
指针形式:
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = , maxm = , INF = 0x7fffffff;
int tot;
queue<int> q; struct state
{
int next[];
int fail, cnt;
}trie[]; void init()
{
while(!q.empty()) q.pop();
for(int i=; i<maxm; i++)
{
mem(trie[i].next, );
trie[i].fail = trie[i].cnt = ;
}
tot = ;
} void insert(char *s)
{
int n = strlen(s);
int rt = ;
for(int i=;i<n; i++)
{
int x = s[i] - 'a';
if(!trie[rt].next[x])
{
trie[rt].next[x] = ++tot;
}
rt = trie[rt].next[x];
}
trie[rt].cnt++;
} void build()
{
trie[].fail= -;
q.push();
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i=; i<; i++)
{
if(trie[u].next[i])
{
if(u == ) trie[trie[u].next[i]].fail = ;
else{
int v = trie[u].fail;
while(v != -)
{
if(trie[v].next[i])
{
trie[trie[u].next[i]].fail = trie[v].next[i];
break;
}
v = trie[v].fail;
}
if(v == -) trie[trie[u].next[i]].fail = ;
}
q.push(trie[u].next[i]);
}
}
}
} int Get(int u)
{
int res = ;
while(u)
{
res = res + trie[u].cnt;
trie[u].cnt = ;
u = trie[u].fail;
}
return res;
} int math(char *s)
{
int n = strlen(s);
int rt = , res = ;
for(int i=; i<n; i++)
{
int x = s[i] - 'a';
if(trie[rt].next[x]) //如果有儿子 就直接下传
rt = trie[rt].next[x];
else //如果没有 就去fail去找
{
int p = trie[rt].fail;
while(p != - && trie[p].next[x] == ) p = trie[p].fail;
if(p == -) rt = ; //一直没找到 则返回祖结点
else rt = trie[p].next[x];
}
if(trie[rt].cnt) //如果以这个点为后缀的串还没有被匹配 则匹配
res = res + Get(rt);
}
return res; } int T, n;
char s[maxn];
int main()
{
scanf("%d", &T);
while(T--)
{
init();
scanf("%d", &n);
rap(i, , n)
{
scanf("%s", s);
insert(s);
}
build();
scanf("%s", s);
printf("%d\n", math(s));
}
return ;
}
数组形式:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<string>
#include<iostream>
#define maxn 1000010
using namespace std;
int n;
int nxt[maxn][],fail[maxn],edd[maxn],root,L;//nxt记录节点,在这里edd指针代表以当前节点为字符串尾的字符串个数
int vis[maxn];
int newnode()
{
for(int i=;i<;i++)
nxt[L][i]=-;//节点连接的边初始化为-1
edd[L]=;
vis[L]=;
return L++;
}
void init()
{
L=;
root=newnode();
} void insert(char *str)//trie树的建立
{
int l = strlen(str);
int now=root;
for(int i=;i<l;i++)
{
int x = str[i] - 'a';
if(nxt[now][x]==-)nxt[now][x]=newnode();
now=nxt[now][x];
}
edd[now]++;
}
void build()//建立ac自动机
{
queue<int> Q;
for(int i=;i<;i++)
{
if(nxt[root][i]==-)nxt[root][i]=root;
else //若有连边则将节点加入队列 ,并将fail指针指向root
{
fail[nxt[root][i]]=root;
Q.push(nxt[root][i]);
}
}
while(!Q.empty())
{
int now=Q.front();
Q.pop();
for(int i=;i<;i++)
{
if(nxt[now][i]==-) //若无连边,则将该边指向当前节点fail指针指向的相应字符连接的节点
nxt[now][i]=nxt[fail[now]][i];
else //若有连边,则将儿子节点的fail指针指向当前节点fail指针指向相应字符接的节点
{
fail[nxt[now][i]]=nxt[fail[now]][i];
Q.push(nxt[now][i]); //加入队列继续遍历
}
}
}
}
int query(char str[])
{
int l = strlen(str);
int now=root;
int res=;
for(int i=;i<l;i++)
{
int x = str[i] - 'a';
now=nxt[now][x];
int temp=now;
while(temp!=root&&vis[temp]==)//根据题目要求改变形式
{
res+=edd[temp];
edd[temp]=;
vis[temp]=;
temp=fail[temp];
}
}
return res; //在这里返回的是匹配到的模式串的数量
}
char str[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
int ma=;
for(int i=;i<n;i++)
{
scanf("%s",str);
insert(str);
}
scanf("%s", str);
build();
int sum=query(str);
printf("%d\n", sum);
}
}
Keywords Search HDU - 2222(ac自动机板题。。)的更多相关文章
- Keywords Search HDU - 2222 AC自动机板子题
In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey al ...
- HDU 2222 AC自动机模板题
题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...
- hdu 2222(AC自动机模版题)
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- HDU 2222 AC自动机(模版题)
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- HDU 2222 AC自动机 裸题
题意: 问母串中出现多少个模式串 注意ac自动机的节点总数 #include <stdio.h> #include <string.h> #include <queue& ...
- HDU 2222 AC自动机模版题
所学的AC自动机都源于斌哥和昀神的想法. 题意:求目标串中出现了几个模式串. 使用一个int型的end数组记录,查询一次. #include <cstdio> #include <c ...
- AC日记——Keywords Search hdu 2222
2222 思路: ac自动机模板题: 代码: #include <cstdio> #include <cstring> #include <iostream> #i ...
- HDU 3065 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模 ...
- HDU 2896 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意:多个模式串.多个匹配串.其中串的字符范围是(0~127).问匹配串中含有哪几个模式串 ...
- HDU-2222 Keywords Search 字符串问题 AC自动机
题目链接:https://cn.vjudge.net/problem/HDU-2222 题意 给一些关键词,和一个待查询的字符串 问这个字符串里包含多少种关键词 思路 AC自动机模版题咯 注意一般情况 ...
随机推荐
- BZOJ3174. [TJOI2013]拯救小矮人(dp)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3174 题解 其实此题并不需要那么多YY的部分. 我们考虑若干个小矮人逃出的顺序.若跳出的 ...
- 我们一起学习WCF 第八篇回调函数
什么是回调函数? 一个简单的例子:小明想要在京东购买一件商品.他会登陆网站选好自己的商品.然后他把这件商品放在购物车,然后开始付钱(这个表示触发,不付钱不发货(排除货到付款)).然后京东的人员收到了小 ...
- C#与mongoDB初始环境搭建
mongoDB官网https://www.mongodb.com/ mongoDB默认安装路径(Windows x64平台) C:\Program Files\MongoDB\Server\3.4\b ...
- java.lang.Boolean.valueOf(String s)
简单说,就是s为true(这四个字母大小写任意)时,返回值为true,否则为false public class one { public static void main(String[] args ...
- Java EE平台介绍(译)
Java EE平台介绍 2.1 企业应用总览 这一部分将对企业应用及其设计和开发进行简单介绍. 就像之前说的,Java EE 平台是为了帮助开发者开发大规模.多层次.可伸缩.服务可靠.网络安全的应用而 ...
- NO--10今天带大家回忆回忆“闭包”吧!
对于‘闭包,我相信很多人都掉进过这个坑里,也相信很多人没能详细的理解这个问题,今天带大家再次走进闭包: 写这篇文章时的心情是十分忐忑的,因为对于我们今天的主角:闭包,很多小伙伴都写过关于它的文章,相信 ...
- spring-boot 项目整合logback
使用spring-boot项目中添加日志输出,java的日志输出一共有两个大的方案log4j/log4j2 ,logback.log4j2算是对log4j的一个升级版本. 常规做法是引入slf4j作为 ...
- scikit-learn使用PCA降维小结
本文在主成分分析(PCA)原理总结和用scikit-learn学习主成分分析(PCA)的内容基础上做了一些笔记和补充,强调了我认为重要的部分,其中一些细节不再赘述. Jupiter notebook版 ...
- Android开发第二阶段(3)
今天:对闹钟代码的按钮事件进行了添加和修改.对监听器的相关应用也有了进一步的了解和深入. 明天:对主界面的代码的优化比如对按钮位置的调节等细节处理.
- Spring 依赖的Jar包简介
Spring 依赖的Jar包简介 Spring的依赖关系 依赖关系分组 JAR文件 说 明 ant ant.jar, ant-junit.jar, ant-launcher.jar Spring采用A ...