HDU 2846 Trie

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
疫情居家办公系统管理系统按照操作主体分为管理员和用户。管理员的功能包括办公设备管理、部门信息管理、字典管理、公告信息管理、请假信息管理、签到信息管理、留言管理、外出报备管理、薪资管理、用户管理、公司资料管理、管理员管理。用户的功能等。该系统采用了MySQL数据库,Java语言,Spring Boot框架等技术进行编程实现。 疫情居家办公系统管理系统可以提高疫情居家办公系统信息管理问题的解决效率,优化疫情居家办公系统信息处理流程,保证疫情居家办公系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理疫情居家办公系统信息,包括外出报备管理,培训管理,签到管理,薪资管理等,可以管理公告。 外出报备管理界面,管理员在外出报备管理界面中可以对界面中显示,可以对外出报备信息的外出报备状态进行查看,可以添加新的外出报备信息等。签到管理界面,管理员在签到管理界面中查看签到种类信息,签到描述信息,新增签到信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值