HDU 2846(Trie树)
题面:
Total Submission(s): 6650 Accepted Submission(s): 2143
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;
}