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. c++中编译器的作用

    编译器的部分工作是寻找程序代码中的错误.编译器不能查出程序的意义是否正确. 但它能够查出程序形式上的错误.以下是编译器能查出的最普遍的一些错误: (1)语法错误.程序猿犯了c++语言中的语法错误. ( ...

  2. Android之后台服务判断本应用Activity是否处于栈顶

    在Android开发中,我们经常想知道是否自己的服务处于后台运行中,因为在后台运行的服务器优先级会降低,也就极有可能会被系统给回收掉,有什么好办法呢?Google推荐我们将服务运行到前台,如何知道服务 ...

  3. jdom dom4j解析xml不对dtd doctype进行验证(转)

    一.写在所有之前:因为dom4j和jdom在这个问题上处理的方法是一模一样的,只是一个是SAXBuilder 一个SAXReader,这里以jdom距离,至于dom4j只需要同理替换一下就可以了.二. ...

  4. uva 10069 Distinct Subsequences(高精度 + DP求解子串个数)

    题目连接:10069 - Distinct Subsequences 题目大意:给出两个字符串x (lenth < 10000), z (lenth < 100), 求在x中有多少个z. ...

  5. script:查看历史sql执行信息

    script:查看历史sql执行信息 SELECT *     FROM (SELECT '1.v$sql'||'实例号:'||GV$SQL.inst_id source,               ...

  6. 2388 Who&#39;s in the Middle(简单排序)

    训练计划的第一个问题,首先从水问题开始:排序的数组,中间数则输出. http://poj.org/problem?id=2388 冒泡排序: #include <iostream> usi ...

  7. Servlet和JSP读书笔记(二)

    一. GenericServlet 1. 前面写的 Servlet和JSP学习笔记(一) 中的实例都是通过实现Servlet接口编写的,这样存在的问题就是:你必须实现Servlet中的所有方法,而不管 ...

  8. 不是技术牛人,如何拿到国内IT巨头的Offer(转)

    不久前,byvoid面阿里星计划的面试结果截图泄漏,引起无数IT屌丝的羡慕敬仰.看看这些牛人,NOI金牌,开源社区名人,三年级开始写Basic…在跪拜之余我们不禁要想,和这些牛人比,作为绝大部分技术屌 ...

  9. ISO-8859-1乱码恢复

    为兼容较旧的jQuery插件,我把jQuery版本号从2.1.x降到了1.8.x,这比加入jquery-migration插件要来得干脆. 我没把这两个版本号的的区别一一记下来,而是直接改个版本号号. ...

  10. 第m个全排列

    #include<stdio.h> #include<string.h> int flag,n,m; ],sum,vis[]; void dfs(int k) { ) retu ...