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):
trie树代码:
trie树详解:
Trie树详解及其应用(引用)
对于每一个给出的字符串,都在一个给定的词典里面找到以这个字符串开头的所有单词个数”。
输入
输入的第一行为一个正整数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树详解及其应用(引用)
相关文章推荐
- 存储过程、触发器和用户自定义函数实验(用户自定义函数)
- Notepad++设置无扩展名文件的默认打开程序
- 简单的鼠标滑动上去图片放大Jquery特效代码
- 实习杂记(21):LocalBroadcastManager的使用、优点在哪里?
- AutoCAD中程序化加载.NET程序集的方法(1)
- VC程序快速删除自己(可能做升级程序的时候有用)
- 软件护眼设置汇总
- 【Java学习-J.160601.0.20】一个验证码的servlet
- 正则表达式30分钟入门教程
- 让程序出现在控制面板(写注册表)
- HI3531开发板开机LOG文本,在学习开发板时帮我挺大
- AutoCAD中程序化加载.NET程序集的方法
- Exchange 学习网站
- opencv学习笔记之一(数据的复制)
- Android初级教程Activity小案例(计算器乘法运算)
- Samba服务器配置
- RadioButton图片变形的问题
- 乐学成语(1)
- 冒泡排序
- 20款Notepad++插件下载和介绍