【HDU 1247】字典树 一个单词由两个单词组成
来源:互联网 发布:java项目中的角色 编辑:程序博客网 时间:2024/05/18 03:13
#include <iostream>#include <string.h>#include <queue>using namespace std;#define MAX 26struct node;typedef struct node *NumTree;struct node{ int tag; NumTree ans[MAX];};NumTree init(NumTree T){ int i; T=new struct node; for(i=0;i<MAX;i++) { T->tag=0; T->ans[i]=NULL; } return T;}void insert(NumTree T,char str[]){ NumTree Q=T,S=NULL; int len=strlen(str); int i,id; for(i=0;i<len;i++) { id=str[i]-'a'; if(Q->ans[id]==NULL) { S=new struct node; int j; for(j=0;j<MAX;j++) { S->ans[j]=NULL; S->tag=0; } Q->ans[id]=S; Q=Q->ans[id]; } else { Q=Q->ans[id]; } } Q->tag=1;}int find(NumTree T,char str[]){ NumTree Q=T; int len=strlen(str); int i,id; queue<int>Stack; for(i=0;i<len;i++) { id=str[i]-'a'; if(Q->ans[id]!=NULL) { Q=Q->ans[id]; } if(Q->tag && i<len)//find sepraste point { Stack.push(i); } } while(!Stack.empty()) { int now=Stack.front(); now++; bool OK=true; Stack.pop(); Q=T; while(str[now]) { id=str[now++]-'a'; if(Q->ans[id]==NULL) { OK=false; break; } Q=Q->ans[id]; } if(OK && Q->tag) return 1; } return 0;}int main(){ char str[50011][20]; NumTree T=NULL; int x=0; T=init(T); while(gets(str[x]) && str[x][0]!='\0') { insert(T,str[x]); x++; } int u; for(u=0;u<x;u++) { if(find(T,str[u])==1) cout<<str[u]<<endl; } return 0;}
搞了一下午····
不得不说还是有一些收获,RE的次数最多,
这里要说一下,RE分两种,一种越界,一种是栈溢出,
这里在定义str的时候,
如果定义str[50001][100],就会栈溢出,可见字典树对字符长度的要求很高,不能太长。
整个代码的思路就是在insert同时的时候标记,一个字符如果是一个字符串的结尾字符,那么标记,
在find的时候,如果找到了一个标记,找到了A个标记,说明这个字符串里含有A个字符串,但无法确定这A个字符串是否是紧邻的,这里需要用STACK或者QUEUE,最好还是用STACK,依次记录有标记的下标,然后从后往前开始查询,
这里还有一个小细节,在查询的时候now++,因为top回来的now是一个字符的结尾,重新遍历的时候应该是从找到标记的字符的后一个字符开始。
然后如果有两个以上标记是怎么回事呢?
如果
abcdefg
1001001
有三个标记,这时候从最后一个1开始找,然后从倒数第二个1找,而这里的1代表,至少字典里有a,abcd,abcdefg三个字符串(也可能有defg,bcd等等),也就是说我从标记的下一个字符开始找起,标记的前半部分已经肯定在字符串里了(也就是组成该字符串的前半段),只需要证明从标记开始的字符串也在字典树里,那么就满足该字符串由两个字符串构成,输出即可。
这题还有一个思路,就是把每一个字符串在不同位置“砍一刀”,变成两个字符串,然后find(str1)find(str2),如果都能找到,那么就说明它(这个字符串)有两个字符串构成,这个代码我也实现了,但是不知道为什么一直RE,可能是迭代或者递归的层数太多了(find要递归,如果字符串很长的话,也要砍很多刀)。暂时我还没有想到比较好的优化方案。砍刀也许可以用二分查找实现,但那仍然依赖输入。对效率提升不一定十分明显。
#include <iostream>#include <string.h>using namespace std;#define MAX 26struct node;typedef struct node *NumTree;struct node{ NumTree ans[MAX];};NumTree init(NumTree T){ int i; T=new struct node; for(i=0;i<MAX;i++) T->ans[i]=NULL; return T;}void insert(NumTree T,char str[]){ NumTree Q=T,S=NULL; int len=strlen(str); int i,id; for(i=0;i<len;i++) { id=str[i]-'a'; if(Q->ans[id]==NULL) { S=new struct node; int j; for(j=0;j<MAX;j++) S->ans[j]=NULL; Q->ans[id]=S; Q=Q->ans[id]; } else { Q=Q->ans[id]; } }}int find(NumTree T,char str[]){ NumTree Q=T; int len=strlen(str); int i,id; int tag=1; for(i=0;i<len;i++) { id=str[i]-'a'; if(Q->ans[id]!=NULL) Q=Q->ans[id]; else { tag=0; break; } } return tag;}void FreeTree(NumTree T){ int i; for(i=0;i<MAX;i++) { if(T->ans[i]!=NULL) FreeTree(T->ans[i]); } free(T);}int main(){ char str[50011][100]; NumTree T=NULL; int x=0; T=init(T); while(gets(str[x]) && str[x][0]!='\0') { insert(T,str[x]); x++; } int u; for(u=0;u<x;u++) { int i,j,k=1; int len=strlen(str[u]); char str1[100],str2[100]; while(k<len) { for(i=0;i<k;i++) str1[i]=str[u][i]; str1[i]='\0'; for(j=0;i<len;i++,j++) str2[j]=str[u][i]; str2[j]='\0'; if(find(T,str1) && find(T,str2)) { printf("%s\n",str[u]); break; } k++; } } //FreeTree(T); return 0;}
- 【HDU 1247】字典树 一个单词由两个单词组成
- 查看是否由两个单词组成
- HDU 1247 字典树 拆分单词
- 给一个由n个单词组成的字符串排序
- HDU 1247 trie 一个单词是否是两个单词的连接
- hdu 1247 Hat’s Words 字典树统计单词
- hdu 1247 Hat’s Words 字典树单词拼接
- hdu 2072 单词数(字典树)
- hdu 2072 单词数 字典树
- HDU 2072 单词数 字典树
- hdu 2072 单词数 字典树
- hdu 2072-单词数(字典树)
- hdu-2072-单词数(字典树)
- Hard 找到由其它单词组成的最长单词 @CareerCup
- 阿里校招笔试——给定一个字符串S和有效单词的字典D,请确定可以插入到S中的最小空格数,使得最终的字符串完全由D中的有效单词组成,并输出解。
- 给出一个2D板和字典中的单词列表,找到棋盘上的所有单词。每个单词必须由顺序相邻单元格的字母构成。不能重复使用
- HDU 1075 字典树 树搜索 逆路径输出单词
- hdu 2846 【字典树】单词子串的匹配数
- 数据结构-----1的数目
- 递归列出指定目录下的所有文件的绝对路径
- 检索COM类工厂中CLSID为{000209FF-0000-0000-C000-000000000046}的组件时失败,原因是出现以下错误: 80070005
- 各种标签引用
- .NET MVC 文件上传下载
- 【HDU 1247】字典树 一个单词由两个单词组成
- 搜索指定目录下是否存在某个文件
- Servlet生命周期与工作原理
- JavaScript 思考总结(一)JavaScript是什么
- 数据库语言
- [LeetCode] Combinations [38]
- gflags摘记
- FPGA学习的一些误区
- MFC开机自启动(写注册表)