您的位置:首页 > 其它

hiho一下~week_2:从简单匹配—>hash—>trie树

2016-06-10 22:24 393 查看
题目意思:

对于每一个给出的字符串,都在一个给定的词典里面找到以这个字符串开头的所有单词个数”。

输入

输入的第一行为一个正整数n,表示词典的大小,其后n行,每一行一个单词,单词由不超过10个的小写英文字母组成,可能存在相同的单词,此时应将其视作不同的单词。接下来的一行为一个正整数m,表示小Hi询问的次数,其后m行,每一行一个字符串,该字符串由不超过10个的小写英文字母组成,表示小Hi的一个询问。

输出

对于小Hi的每一个询问,输出一个整数Ans,表示词典中以小Hi给出的字符串为前缀的单词的个数。

样例输入

5

babaab

babbbaaaa

abba

aaaaabaa

babaababb

5

babb

baabaaa

bab

bb

bbabbaab

样例输出

1

0

3

0

0

题目分析:

方法一、直接暴力匹配,时间复杂度O(n*m)。

方法二、利用hash时间复杂度,记录每个字符串的前缀的个数,直接进行查找,时间复杂度O(len*n),len是字符串的长度。

方法三、trie树,建树的时间复杂度是O(len*n),查询的时间复杂度是O(len)。

方法二代码(TL):

//方法二hash
void showHash(){
map<string,int> cnt;
string s;
int n,m;
while(cin>>n){
cnt.clear();
for(int i=0;i<n;i++){
cin>>s;
string ss="";
for(int i=0;i<s.size();i++){
ss+=s[i];
cnt[ss]++;//记录每一个前缀的出现次数
}
}
cin>>m;
for(int i=0;i<m;i++){
cin>>s;
cout<<cnt[s]<<endl;
}
}
}


trie树代码:

/**
*Author: xiaoran
*Solution:trie树
*
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<time.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<fstream>
#define LL long long
using namespace std;
const int MAXN=1000005;

typedef struct Trie_node
{
int cnt; // 统计单词前缀出现的次数
struct Trie_node* next[26]; // 指向各个子树的指针
bool exist; // 标记该结点处是否构成单词
}TrieNode , *Trie;
//其中next是一个指针数组,存放着指向各个孩子结点的指针。

TrieNode * createTrieNode(){//创建一个新的结点
TrieNode * node = (TrieNode *) malloc(sizeof(TrieNode));
node->cnt=0;
node->exist=false;
memset(node->next,0,sizeof(node->next));//初始化数组为未标记
return node;

}
void trieInsert(Trie root,char *str){
Trie node = root;
char *p=str;
int id;
while( *p ){
id = *p - 'a';
if(node->next[id]==NULL){//下一个为空
node->next[id] = createTrieNode();
}
node = node -> next[id];//标记指针下移
++p;
node->cnt+=1;//记录前缀的个数
}
node->exist = true;//该单词存在
}
int trieSearch(Trie root,char *str){//查询前缀的个数
Trie node = root;
char *p = str;
while( *p ){

int id = *p - 'a';
node = node->next[id];
++p;
if(node==NULL){//没有该单词
return 0;
}
}
return node->cnt;//返回次数
}

//方法二hash void showHash(){ map<string,int> cnt; string s; int n,m; while(cin>>n){ cnt.clear(); for(int i=0;i<n;i++){ cin>>s; string ss=""; for(int i=0;i<s.size();i++){ ss+=s[i]; cnt[ss]++;//记录每一个前缀的出现次数 } } cin>>m; for(int i=0;i<m;i++){ cin>>s; cout<<cnt[s]<<endl; } } }int main()
{

//freopen("E:/input.txt","r",stdin);
//freopen("E:/output.txt","w",stdout);
char str[15];
int n,m;
while(scanf("%d",&n)==1){
Trie root = createTrieNode();//初始化根节点
for(int i=0;i<n;i++){
scanf("%s",str);
trieInsert(root , str);
}
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%s",str);
printf("%d\n",trieSearch(root,str));
}
}

//showHash();
return 0;
}


trie树详解:

Trie树详解及其应用(引用)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: