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