hdu 2846(字典树变型)询问子串出现的次数

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

题意是给出一些模式串,再给出几个询问,询问给出的字符串在多少个模式串中出现
比如字符串abc所含的字串有a,ab,abc,b,bc,c
可用字典树解决,字典树能很好的处理前缀出现的次数,所以可将模式串分解,依次插入
需要注意的是对于同一个模式串的不同子串可能有相同的前缀,为了避免多次计算,可以添加字典树节点的信息,添加num记录最后插入的字符串是第num个模式串的子串

ac自动机t了= =醉了 因为长度比较短,所以直接用字典树暴力插入就好
容易re,开500000我也不知道为啥,我算出来如果不重复的话会有 (1+2…+20)*10000
那么应该是400万,但是肯定会有重复的,因为每一层也就26,所以50万基本就够了

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 500000;
const int CASE_SIZE = 26;

struct Trie
{
    int child[MAXN][CASE_SIZE],value[MAXN],trieN,root;
    int id[MAXN];
    void init()
    {
        trieN=root=0;value[root]=0;
        memset(child[root],-1,sizeof(child[root]));
    }
    int newnode()
    {
        trieN++;value[trieN]=0;
        memset(child[trieN],-1,sizeof(child[trieN]));
        return trieN;
    }
    void insert(char *s,int k)
    {
        int x=root;
        for(int i=0;s[i];i++)
        {
            int d=s[i]-'a';
            if(child[x][d]==-1)
                child[x][d]=newnode();
            x=child[x][d];
            if(id[x]!=k)
            {
                value[x]++;
                id[x]=k;
            }
        }
    }
    int search(char *s)
    {
        int sum=0,x=root;
        for(int i=0;s[i];i++)
        {
            int d=s[i]-'a';
            if(child[x][d]==-1)
                return 0;
            x=child[x][d];
        }
        sum+=value[x];
        return sum;
    }
}trie;


char s[26];
char ss[26];

int main()
{
    int n;
    scanf("%d",&n);
    trie.init();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s);
        int len=strlen(s);
        for(int j=0;j<len;j++)
            trie.insert(s+j,i);
    }
    int m;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",ss);
        printf("%d\n",trie.search(ss));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章