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 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

題目大意:給你一系列完整字符串,然後再給你一些殘缺的字符串,輸出每個殘缺的字符串可能出現在哪些字符串中,輸出這些字符串的總數。

解題思路:因爲這個題讓你輸出的是可能在那些字符串中出現,注意這裏並不是要求作爲前綴,所以我們不妨也將每個完整的字符串分解(如:add 可以分解爲 add dd d),然後用它們來構建字典樹,並記錄每個字符出現在幾個字符串中,這裏需要注意的是在將一個字符串分解成多個字符串時只算出現在一個字符串中。最後的搜索操作和普通的搜索操作並無區別。

#include <iostream>
#include <string>
#include <cstdio>

using namespace std;
struct Trie{
    int cnt,pre;///cnt記錄有多少個字符串經過這個節點,pre記錄上一次經過這個節點的字符串的序號
    Trie *child[26];
    Trie()
    {
        pre = -1;
        cnt = 0;
        for(int i=0;i<26;i++)
            child[i]=NULL;
    }
};
Trie *root,*current,*temp;
void insert(string str,int k)///k代表當前傳入的這個字符串的序號
{
    current = root;
    for(int i=0;i<str.length();i++)
    {
        if(current->child[str[i]-'a'] == NULL){
            temp = new Trie;
            current->child[str[i]-'a'] = temp;
            current = current->child[str[i]-'a'];
        }
        else{
            current = current->child[str[i]-'a'];
        }
        if(current->pre!=k) current->cnt++;///如果這個字符串和上一個字符串的序號不同這時的cnt需要加1
        current->pre = k;
    }
}
int search(string str)
{
    current = root;
    for(int i=0;i<str.length();i++)
    {
        if(current->child[str[i]-'a']== NULL)
            return 0;
        current = current->child[str[i] - 'a'];
    }
    if(current!=NULL)///如果這個字符串在字典樹中存在,就輸出經過這個節點的字符串個數,否則就輸出0
        return current->cnt;
    else
        return 0;
}
void del(Trie *root)
{
    for(int i = 0; i < 26; i++)
        if(root->child[i]!=NULL)
            del(root->child[i]);
    delete(root);
}
int main()
{
    int p,q;
    string str;
    root = new Trie;
    scanf("%d",&p);
    for(int i=0;i<p;i++)
    {
        cin>>str;
        string s;
        int len = str.length();
        for(int j=0;j<len;j++)
        {
            s = str.substr(j,len);///將原本的字符串分解成不同的子串,插入字典樹
            insert(s,i);
        }
    }
    scanf("%d",&q);
    for(int i=0;i<q;i++)
    {
        cin>>str;
        printf("%d\n",search(str));
    }
    del(root);
    return 0;
}
發佈了105 篇原創文章 · 獲贊 15 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章