Repository
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 4917 Accepted Submission(s): 1707
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
字典树的一道经典题,之前我的思路是Trie+bfs,结果超时,后来发现只需要将每个字符串的子串分别拿出来插入到Trie里面,这时检索到的子串数目就是总的子串数目,另外为了避免一个字符串的重复子串多次计数(如ababab的ab子串),应在插入时加个标记,我用的是ID.
但另外存在一个内存消耗的问题。
我的指针版本虽然能在C++中AC,但因为指针在G++中占8个字节,所以用G++会超内存。
后来经学长指点,学习了一下数组般的Trie,同样的检索效率,内存占用却低了很多,而且代码简短了很多。下面是AC代码:
指针
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include<cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cctype>
#include<queue>
#include<map>
using namespace std;
const int maxn = 26;
struct Trie{
int v,ID;
Trie *next[maxn];
};
Trie *root;
void creatTrie(char* str,int num){
int len = strlen(str),i,j;
Trie *p = root,*q;
for(i=0 ;i<len ;i++){
int id = str[i] - 'a';
if(p->next[id] == NULL){
q = (Trie*)malloc(sizeof(Trie));
q->v = 1;
q->ID = num;
for(j=0 ;j<maxn ;j++){
q->next[j] = NULL;
}
p->next[id] = q;
}
p = p->next[id];
if(p->ID != num){
p->v++;
p->ID = num;
}
}
}
int findTrie(char* str){
int i;
int len = strlen(str);
Trie *p = root;
for(i=0 ;i<len ;i++){
int id = str[i] - 'a';
p = p->next[id];
if(p == NULL)
return 0;
}
return p->v;
}
int dealTrie(Trie* T)
{
if(T==NULL)
return 0;
for(int i = 0; i < maxn; i++)
{
if(T->next[i]!=NULL)
dealTrie(T->next[i]);
}
free(T);
return 0;
}
int main(){
char str[55];
int P,i,j;
root = (Trie*)malloc(sizeof(Trie));
for(i=0 ;i<maxn ;i++){
root->next[i] = NULL;
}
root->ID = -1;
root->v = 0;
scanf("%d",&P);
for(i=0 ;i<P ;i++){
scanf("%s",str);
int len = strlen(str);
for(j=0 ;j<len ;j++){
creatTrie(str+j,i);
}
}
int n;
scanf("%d",&n);
for(i=0 ;i<n ;i++){
scanf("%s",str);
printf("%d\n",findTrie(str));
}
dealTrie(root);
return 0;
}
数组:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
int Trie[maxn][27];
int num;
int val[maxn],vis[maxn];
void init(void){
num = 1;
memset(Trie,0,sizeof(Trie));
memset(val,0,sizeof(val));
memset(vis,0,sizeof(vis));
}
void creatTrie(char* str,int ID){
int p = 0,id,i;
int len = strlen(str);
for(i=0 ;i<len ;i++){
id = str[i] - 'a';
if(!Trie[p][id]){
Trie[p][id] = num++;
vis[Trie[p][id]] = ID;
val[Trie[p][id]]++;
}
p = Trie[p][id];
if(vis[p] != ID){
val[p]++;
vis[p] = ID;
}
}
}
int findTrie(char* str){
int i,id,p = 0,len = strlen(str);
for(i=0 ;i<len ;i++){
id = str[i] - 'a';
if(!Trie[p][id]){
return 0;
}
p = Trie[p][id];
}
return val[p];
}
int main(){
init();
int P,i,j;
scanf("%d",&P);
char str[55];
for(i=1 ;i<=P ;i++){
scanf("%s",str);
int len = strlen(str);
for(j=0 ;j<len ;j++){
creatTrie(str+j,i);
}
}
int k;
scanf("%d",&k);
while(k--){
scanf("%s",str);
printf("%d\n",findTrie(str));
}
return 0;
}