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));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章