HDU 2846 Repository (Trie·统计子串)

题意  给你p个商品名称  然后输入q个字符串查询  对每个查询输出含有查询串为子串的商品个数

Trie能很快的求出字典中以某个串为前缀的串的个数    但现在要查的是以某个串为子串的串的个数  可以发现

一个串的任何子串肯定是这个串某个后缀的前缀  如"ri"是“Trie" 的子串  是后缀 "rie" 的前缀

那么我们在向Trie中插入时可以把这个串的所有后缀都插入 插入时要注意来自同一个串的后缀的相同前缀只能统计一次  如 "abab" 这个串  "ab" 既是后缀 "abab" 的前缀  也是后缀 "ab" 的前缀  但是只能统计一次  这用一个id数组标记就行了

这样最后Trie中以查询串为前缀的串的个数就是原始串中以查询串为子串的串的的个数了

#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e6 + 5;
int trie[N][26], cnt[N], id[N], L;

void insertTrie(char s[], int iid)
{
    int r = 0, i = 0, j;
    while(s[i])
    {
        j = s[i++] - 'a';
        if(!trie[r][j])
            trie[r][j] = L++;
        r = trie[r][j];
        if(id[r] != iid) ++cnt[r];
        id[r] = iid;//标记当前前缀id 保证来自相同串的只自增一次
    }
}

int searchTrie(char s[])
{
    int r = 0, i = 0, j;
    while(s[i])
    {
        j = s[i++] - 'a';
        if(!trie[r][j])
            return 0;
        r = trie[r][j];
    }
    return cnt[r];
}

int main()
{
    L = 1;//初始化Trie
    char s[30];
    int p, q;
    scanf("%d", &p);
    for(int i = 1; i <= p; ++i)
    {
        scanf("%s", s); //插入s的所有后缀
        for(int j = 0; s[j]; ++j)
            insertTrie(s + j, i);
    }

    scanf("%d", &q);
    while(q--)
    {
        scanf("%s", s);
        printf("%d\n", searchTrie(s));
    }

    return 0;
}
//Last modified :   2015-07-28 08:33

Repository

Problem Description

When you go shopping, you can search in repository for avalible merchandises by the computers and internet. First you give the search system a name about something, then the system responds with the results. Now you are given a lot merchandise names in repository
and some queries, and required to simulate the process.

Input

There is only one case. First there is an integer P (1<=P<=10000)representing the number of the merchanidse names in the repository. The next P lines each contain a string (it‘s length isn‘t beyond 20,and all the letters are lowercase).Then there is an integer
Q(1<=Q<=100000) representing the number of the queries. The next Q lines each contains a string(the same limitation as foregoing descriptions) as the searching condition.

Output

For each query, you just output the number of the merchandises, whose names contain the search string as their substrings.

Sample Input

20
ad
ae
af
ag
ah
ai
aj
ak
al
ads
add
ade
adf
adg
adh
adi
adj
adk
adl
aes
5
b
a
d
ad
s

Sample Output

0
20
11
11
2

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-10 13:57:42

HDU 2846 Repository (Trie·统计子串)的相关文章

hdu 2846 Repository 字典树

// hdu 2846 Repository 字典树 // // 题目大意: // // 有n个字符串,m个待询问的字符串,问这些字符串里面以该询问的 // 字符串为子串的字符串有多少个 // // 解题思路: // // 字典树,将字符串的所有子串插入到字典树中,并设立一个No.标识 // 以免重计数.最后查询就好了 // // 感悟: // // 这题的数据量有点大,虽然p是10000,但是长度是20,单个字符串的 // 最大子串数粗略的估计是 20 * 20 ,所以开的空间也要比较大.开始

HDU 2846 Repository(字典树,标记)

题目 字典树,注意初始化的位置~!!位置放错,永远也到不了终点了org.... 我是用数组模拟的字典树,这就要注意内存开多少了,,要开的不大不小刚刚好真的不容易啊.... 我用了val来标记是否是同一个串分解而来的,保存的是串的编号 num记录数目. //string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[firs

HDU 2846 Repository(字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846 题目:输入个n个词典串,然后输入q个串,对这q个串分别输出每个串都是几个词典串的子串. 思路:因为要包含子串,比如abd,将串abd,bd,d都插入字典树,然后每个节点下统计子树个数,直接查找前缀就可以了.但需要注意dcda这种的,需要插入dcda,cda,da,a,这个时候d下面的子树应该是一个而不是2个,因为dcda和da属于同一个词典串.所以在插入的时候进行处理即可. 代码 #inclu

HDU 2846 Repository(字典树变形)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846 Problem Description When you go shopping, you can search in repository for avalible merchandises by the computers and internet. First you give the search system a name about something, then the syst

HDU 2846 Repository (字典树 后缀建树)

Repository Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2932    Accepted Submission(s): 1116 Problem Description When you go shopping, you can search in repository for avalible merchandises

hdu 2846 Repository 字典树的一种变形

Repository Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2633    Accepted Submission(s): 1028 Problem Description When you go shopping, you can search in repository for avalible merchandises

hdu 2846 Repository

字典树 将每个字符串的所有前缀插入进树,采用ID防止重复即可 #include<iostream> #include<cstring> #include<string> using namespace std; string str; int n; int id; struct stu { int m; int id; stu* a[26]; stu() { m=id=0; //memset(a,NULL,sizeof(a)); for(int i=0;i<26;

poj 3461 Oulipo(kmp统计子串出现次数)

题意:统计子串出现在主串中的次数 思路:典型kmp #include<iostream> #include<stdio.h> #include<string.h> using namespace std; int next[10005]; void GetNext(char t[]){//求next数组 int j,k,len; j=0; k=-1; next[0]=-1; len=strlen(t); while(j<len){ if(k==-1||t[j]==

hdu 3065 AC自动机(各子串出现的次数)

病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10324    Accepted Submission(s): 3633 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的“万恶之源”.这是一个庞大的病毒网站,他有着好多好多的病毒,但