hdu5384

给定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树)的更多相关文章

  1. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  2. 基于trie树的具有联想功能的文本编辑器

    之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...

  3. hihocoder-1014 Trie树

    hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...

  4. 洛谷P2412 查单词 [trie树 RMQ]

    题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词 ...

  5. 通过trie树实现单词自动补全

    /** * 实现单词补全功能 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #incl ...

  6. #1014 Trie树

    本题主要是求构造一棵Trie树,即词典树用于统计单词. C#代码如下: using System; using System.Collections.Generic; using System.Lin ...

  7. Trie树-字典查找

    描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题: ...

  8. Trie树的创建、插入、查询的实现

    原文:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28977986&id=3807947 1.什么是Trie树 Tr ...

  9. Trie树(c++实现)

    转:http://www.cnblogs.com/kaituorensheng/p/3602155.html http://blog.csdn.net/insistgogo/article/detai ...

  10. [转]双数组TRIE树原理

    原文名称: An Efficient Digital Search Algorithm by Using a Double-Array Structure 作者: JUN-ICHI AOE 译文: 使 ...

随机推荐

  1. 【ASP.NET Web API教程】4.2 路由与动作选择

    原文:[ASP.NET Web API教程]4.2 路由与动作选择 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内容. 4.2 Routing ...

  2. 使用Understand获取某个函数(方法)的静态度量指标

    在之前的一篇日志中,我简单总结了调用Understand的Perl API的方法,这里再简单总结一些经验: 在SciTools\doc\manuals\pdf目录下的understand_api.pd ...

  3. 在toolbar里动态创建多个button(ext.net)

    private void setOneMenu() { string sql = "select id,name,gids from Config where name<>'高级 ...

  4. Swift - 解析JSON数据(内置NSJSONSerialization与第三方JSONKit)

    一,使用自带的NSJSONSerialization 苹果从IOS5.0后推出了SDK自带的JSON解决方案NSJSONSerialization,这是一个非常好用的JSON生成和解析工具,效率也比其 ...

  5. Linux下select, poll和epoll IO模型的详解

    http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll 介绍 Epoll 可是当前在 Linux 下开发大规模并发网络程序的热 ...

  6. QT断点续传(原理:需要在HTTP请求的header中添加Rang节,告诉服务器从文件的那个位置开始传输.格式为bytes 开始传输的位置)

    //功能:    根据一个URL地址将数据保存到指定路径下,支持断点续传//参数:    url            --需要访问的URL地址//         SavePath       -- ...

  7. Android常用控件之RatingBar的使用

    RatingBar控件比较常见就是用来做评分控件,先上图看看什么是RatingBar 在布局文件中声明 <?xml version="1.0" encoding=" ...

  8. PYQT4 + Python2.6 + eric4-4.2.2a的安装全过程

    PYQT4 + Python2.6 + eric4-4.2.2a的安装全过程 - beike - ITeye技术网站 PYQT4 + Python2.6 + eric4-4.2.2a的安装全过程 博客 ...

  9. java swing设置frame的高度或图标

    Toolkit kit = Toolkit.getDefaultToolkit();                 Dimension dimension = kit.getScreenSize() ...

  10. 让你提前知道软件开发(22):shell脚本文件操作

    文章1部分 再了解C语言 shell脚本中的文件操作 [文章摘要] 编写shell脚本时,经常会涉及到对文件的操作,比方从文件里读取一行数据.向文件追加一行数据等. 完毕文件读写操作的方法有非常多,了 ...