hdu5384(trie树)
给定n个字符串Ai
给定m个字符串Bi
问所有的Bi在每个Ai中出现了多少次
很显然,对Bi建Trie图,然后每次用Ai去匹配的时候,不断查找当前匹配串的最长后缀,这样就能找到答案了
比赛的时候也这样水过了。(又一次我认为这样不会过,但是交上去却过了)
如有有这样的数据的话
1
1 1
10^5个a
10^5个a
那么时间复杂度是10^10,
其实上面不断查找当前匹配串的最长后缀是没必要的,是重复操作的。
如果我们知道当前匹配串的最长后缀包含了多少个Bi,那么就不用去不断回溯了。
所以我们只要在构建fail指针的时候,处理处当前fail指针指向的字符串包含了多少个Bi,那么就不用不断的回溯了。
(哈哈,学到东西了)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = <<;
/* */
const int N = + ;
struct Node
{
int fail, next[];
int cnt;
void init()
{
fail = -;
cnt = ;
for (int i = ; i < ; ++i)
next[i] = -;
}
}Trie[N];
int size;
void insert(int root, char *str)
{
int idx, cur = root;
for (int i = ; str[i]; ++i)
{
idx = str[i] - 'a';
if (Trie[cur].next[idx] == -)
{
Trie[size].init();
Trie[cur].next[idx] = size++;
}
cur = Trie[cur].next[idx];
}
Trie[cur].cnt++;
}
void makeFail(int root)
{
queue<int> q;
for (int i = ; i < ; ++i)
{
if (Trie[root].next[i] == -)
Trie[root].next[i] = root;
else
{
Trie[Trie[root].next[i]].fail = root;
q.push(Trie[root].next[i]);
}
}
while (!q.empty())
{
int cur = q.front();
q.pop();
for (int i = ; i < ; ++i)
{
if (Trie[cur].next[i] == -)
{
Trie[cur].next[i] = Trie[Trie[cur].fail].next[i];
}
else
{
Trie[Trie[cur].next[i]].fail = Trie[Trie[cur].fail].next[i];
//处理处,当前fail指针指向的字符串包含了多少个Bi
Trie[Trie[cur].next[i]].cnt += Trie[Trie[Trie[cur].fail].next[i]].cnt;
q.push(Trie[cur].next[i]);
} }
}
}
int match(int root, char *str)
{
int i = ;
int idx;
int cur = root;
int ret = ;
while (str[i])
{
idx = str[i] - 'a';
cur = Trie[cur].next[idx];
//int tmp = cur;
//while (tmp != root)
//{
// ret += Trie[tmp].cnt;
// tmp = Trie[tmp].fail;
//} ret += Trie[cur].cnt;
i++;
}
return ret;
}
/*
题目问所有的Bi在每一个Ai中出现的次数 一个串的所有子串可以表示为它所有前缀的后缀
对所有的Bi建trie图
我们可以让每个Ai匹配的时候,就让这个当前字符串不断的去寻找最长后缀,
时间复杂度吵了
,然而数据水,居然过了
*/ char str[];
char str2[];
int main()
{
int t, n, m;
//freopen("d:/in.txt", "r", stdin);
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &m);
int idx = ;
size = ;
Trie[].init();
Trie[].fail = ;
for (int i = ; i < n; ++i)
{
scanf("%s", str + idx);
idx += strlen(str + idx) + ;
}
for (int i = ; i < m; ++i)
{
scanf("%s", str2);
insert(,str2);
}
makeFail();
idx = ;
for (int i = ; i < n; ++i)
{
printf("%d\n", match(, str + idx));
idx += strlen(str + idx) + ;
}
}
return ;
}
hdu5384(trie树)的更多相关文章
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- 基于trie树的具有联想功能的文本编辑器
之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...
- hihocoder-1014 Trie树
hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...
- 洛谷P2412 查单词 [trie树 RMQ]
题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词 ...
- 通过trie树实现单词自动补全
/** * 实现单词补全功能 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #incl ...
- #1014 Trie树
本题主要是求构造一棵Trie树,即词典树用于统计单词. C#代码如下: using System; using System.Collections.Generic; using System.Lin ...
- Trie树-字典查找
描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题: ...
- Trie树的创建、插入、查询的实现
原文:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28977986&id=3807947 1.什么是Trie树 Tr ...
- Trie树(c++实现)
转:http://www.cnblogs.com/kaituorensheng/p/3602155.html http://blog.csdn.net/insistgogo/article/detai ...
- [转]双数组TRIE树原理
原文名称: An Efficient Digital Search Algorithm by Using a Double-Array Structure 作者: JUN-ICHI AOE 译文: 使 ...
随机推荐
- 【ASP.NET Web API教程】4.2 路由与动作选择
原文:[ASP.NET Web API教程]4.2 路由与动作选择 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内容. 4.2 Routing ...
- 使用Understand获取某个函数(方法)的静态度量指标
在之前的一篇日志中,我简单总结了调用Understand的Perl API的方法,这里再简单总结一些经验: 在SciTools\doc\manuals\pdf目录下的understand_api.pd ...
- 在toolbar里动态创建多个button(ext.net)
private void setOneMenu() { string sql = "select id,name,gids from Config where name<>'高级 ...
- Swift - 解析JSON数据(内置NSJSONSerialization与第三方JSONKit)
一,使用自带的NSJSONSerialization 苹果从IOS5.0后推出了SDK自带的JSON解决方案NSJSONSerialization,这是一个非常好用的JSON生成和解析工具,效率也比其 ...
- Linux下select, poll和epoll IO模型的详解
http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll 介绍 Epoll 可是当前在 Linux 下开发大规模并发网络程序的热 ...
- QT断点续传(原理:需要在HTTP请求的header中添加Rang节,告诉服务器从文件的那个位置开始传输.格式为bytes 开始传输的位置)
//功能: 根据一个URL地址将数据保存到指定路径下,支持断点续传//参数: url --需要访问的URL地址// SavePath -- ...
- Android常用控件之RatingBar的使用
RatingBar控件比较常见就是用来做评分控件,先上图看看什么是RatingBar 在布局文件中声明 <?xml version="1.0" encoding=" ...
- PYQT4 + Python2.6 + eric4-4.2.2a的安装全过程
PYQT4 + Python2.6 + eric4-4.2.2a的安装全过程 - beike - ITeye技术网站 PYQT4 + Python2.6 + eric4-4.2.2a的安装全过程 博客 ...
- java swing设置frame的高度或图标
Toolkit kit = Toolkit.getDefaultToolkit(); Dimension dimension = kit.getScreenSize() ...
- 让你提前知道软件开发(22):shell脚本文件操作
文章1部分 再了解C语言 shell脚本中的文件操作 [文章摘要] 编写shell脚本时,经常会涉及到对文件的操作,比方从文件里读取一行数据.向文件追加一行数据等. 完毕文件读写操作的方法有非常多,了 ...