HDU 2846(Trie树)

    题面:

Repository

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 6650    Accepted Submission(s): 2143


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
 

Source
 

    题目描述:先给你P个字符串,再给你Q个字符串,问你这这Q个字符串在P个字符串中出现的次数。
    题面分析:因为这题涉及多个字符串与多个字符串的匹配问题,因此我们可以考虑使用Trie树进行高效的处理。但是需要注意的是,在Trie树的经典题目中,我们只需要判断前缀是否符合即可,但是在这道题上,并没有前缀的限制(即只要出现了即可)。因此我们需要考虑对Trie树进行一定的变形。
   考虑到P个模板串的大小和Q个匹配串的大小最多也才20,因此,我们可以考虑将每个模板串中所对应的字串都一一插入到Trie树即可(但是此时需要注意,因为某些字串可能是相同的,如匹配串abc与abd就有字串ab是相同的,因此还得加入标记数组进行标记去重)
    最后只需要对每个匹配串进行查询即可得出答案了

    
    代码如下:
#include <bits/stdc++.h>
#define maxn 500005
using namespace std;
struct Trie{
    int trie[maxn][26];
    int val[maxn];
    int flag[maxn];
    int sz;
    void init(){
        memset(trie,0,sizeof(trie));
        memset(val,0,sizeof(val));
        memset(flag,-1,sizeof(flag));
        sz=1;
    }
    void Insert(string str,int x){
        int i,len=str.length();
        int u=0;
        for(int i=0;i<len;i++){
            int c=str[i]-'a';
            if(trie[u][c]==0) trie[u][c]=sz++;
            u=trie[u][c];
        }
        if(flag[u]!=x){
            val[u]++;
            flag[u]=x;
        }
    }
    int Search(string str){
        int i,len=str.length();
        int u=0;
        for(int i=0;i<len;i++){
            int c=str[i]-'a';
            if(!trie[u][c]){
                return 0;
            }
            u=trie[u][c];
        }
        return val[u];
    }
}tree;
int main()
{
    //freopen("in.txt","r",stdin);
    tree.init();
    int n,m,i;
    cin>>n;
    string str;
    while(n--){
        cin>>str;
        int len=str.length();
        for(int i=0;i<len;i++){
            for(int j=1;j<len-i+1;j++){
                tree.Insert(str.substr(i,j),n);
            }
        }
    }
    cin>>m;
    for(int i=1;i<=m;i++){
        cin>>str;
        cout<<tree.Search(str)<<endl;
    }
    return 0;
}

posted @ 2018-04-25 16:20  ChenJr  阅读(168)  评论(0编辑  收藏  举报