poj 2804 字典 (特里 要么 快排+二分法)
2804:词典
- 总时间限制:
- 3000ms
- 内存限制:
- 65536kB
- 描写叙述
- 你旅游到了一个国外的城市。那里的人们说的外国语言你不能理解。只是幸运的是,你有一本词典能够帮助你。
- 输入
- 首先输入一个词典。词典中包含不超过100000个词条。每个词条占领一行。每个词条包含一个英文单词和一个外语单词,两个单词之间用一个空格隔开。并且在词典中不会有某个外语单词出现超过两次。词典之后是一个空行。然后给出一个由外语单词组成的文档,文档不超过100000行。并且每行仅仅包含一个外语单词。输入中出现单词仅仅包含小写字母。并且长度不会超过10。
- 输出
- 在输出中,你须要把输入文档翻译成英文,每行输出一个英文单词。假设某个外语单词不在词典中。就把这个单词翻译成“eh”。
- 例子输入
-
dog ogday
cat atcay
pig igpay
froot ootfray
loops oopslay atcay
ittenkay
oopslay - 例子输出
-
cat
eh
loops - 提示
- 输入比較大,推荐使用C语言的I / O函数。
-
-
- 这道题目開始做的时候想到的是字典树;后来由于这道题输入有点特殊。就一直不知道从何下手建树,后来看到别人处理输入的方法;一下子就来了灵感,套用了曾经的模板,把代码敲好提交到百练上就a了,后来在我们学校的oj提交;直接被一个数据难倒了。
。。(百练的数据有点水啊),后来就一直再想解决的方法。開始的那个程序,假设与给的单词部分匹配直到给的单词结束就输出结果了,可是字典树里面还有,不是全然匹配。当时由于a了就没有考虑到这种情况。一直卡在这里;今天看了别人的ac自己主动机的代码;又给了我一点提示;在
- 节点中设置一个单词完结的标记;这种处理,開始我也想了好久,还是有点水啊;一直出现异常的结束。后来最终写好了,感觉还是有点投机取巧的意思,在两个oj上都a了,可是还可以优化;有时候执行还是有问题。我也不知道是什么原因;
- 以下是代码;能ac的,还可以优化啊!
!
-
#include <cstdio>
#include <cstring>
#include <cstdlib>
typedef struct node //节点的结构体
{
char eng[12];
int count; //标记单词是否结束
struct node * next[26];
}node;
int flag;
void Insert(node *T,char *f,char *e) //插入
{
node *p,*q;
p=T;
int len,k;
len=strlen(f);
if(len==0) return ;
for(int i=0;i<len;i++)
{
k=f[i]-'a';
if(p->next[k]==NULL)
{
q=(node*)malloc(sizeof(node)); //添加新节点
for(int i=0;i<26;i++)
{
q->count=0;
strcpy(q->eng,e);
q->next[i]=NULL;
}
p->next[k]=q;
p=q;
}
else
p=p->next[k];
}
p->count++;
}
void Search(node *T,char *s)//查找
{
node *q;
q=T;
int k,i=0,len;
int flag=0;
for(i=0;i<26;i++)
{
k=s[i]-'a';
q=q->next[k];
if(q==NULL)
{
flag=1;
printf("eh\n");
break;
}
if(q->count>0)//单词结束的标记
{
printf("%s\n",q->eng);
flag=1;
break;
}
}
}
void Release(node *T)//销毁
{
for(int i=0;i<26;i++)
if(T->next[i]!=NULL)
Release(T->next[i]);
free(T);
}
int main()
{
//freopen("1.txt","r",stdin);
char english[20],forigen[20];
node *T;
T=(node *)malloc(sizeof(node));
T->count=0;
for(int i=0;i<26;i++)
T->next[i]=NULL;
while(1)
{
english[0]=getchar();
if(english[0]=='\n') break;
scanf("%s %s",english+1,forigen);
Insert(T,forigen,english);
getchar();
}
while(scanf("%s",forigen)!=EOF)
{
flag=0;
Search(T,forigen);
}
Release(T);
return 0;
}第一次ac的水代码;
-
void Search(char *f)
{
node *q;
int len,k;
q=T;
len=strlen(f);
for(int i=0;i<len;i++)
{
k=f[i]-'a';
q=q->next[k];
if(q==NULL)
{
printf("eh\n");
flag=1;
break;
}
}
if(flag==0) printf("%s\n",q->eng);//部分匹配就直接输出了
} - 别人写的字典树代码。好巧妙值得学习;把单词最后一个字符分开处理。做标志,这样就能避免我先前所犯的错误。看了别人的代码,茅塞顿开啊。
-
#include "stdio.h"
#include "string.h"
#include "math.h"
#include "algorithm"
#include "iostream"
using namespace std; typedef struct node
{
struct node *next[26];
char ans[12];
}node; char arr1[12],arr2[12],str[25];
node *T; void Diction()
{
node *q,*p=T;
int i,j,k,len;
len=strlen(arr2);
for(i=0;i<len-1;i++)
{
k=arr2[i]-'a';
if(p->next[k]==NULL){
q=(node*)malloc(sizeof(node));
p->next[k]=q;q->ans[0]=0;
for(j=0;j<26;j++)
q->next[j]=NULL;
p=q;
}else{
p=p->next[k];
}
}
k=arr2[i]-'a';//最后一个字符
if(p->next[k]==NULL){
q=(node*)malloc(sizeof(node));
p->next[k]=q;strcpy(q->ans,arr1);//把arr数组复制给最后一个字符的节点;其它节点都是0
for(j=0;j<26;j++)
q->next[j]=NULL;
}else{
p=p->next[k];
strcpy(p->ans,arr1);
}
} void search()//查询
{
node *p=T;
int i,len,k;
len=strlen(str);
for(i=0;i<len-1;i++)
{
k=str[i]-'a';
if(p->next[k]==NULL){
printf("eh\n");
break;
}else{
p=p->next[k];
}
}
if(i==len-1)//最后一个字符
{
k=str[i]-'a';
if(p->next[k]==NULL){
printf("eh\n");
}else{
p=p->next[k];
if(p->ans[0]!=0)//前面插入那里做的标志
puts(p->ans);
else
printf("eh\n");
}
}
}
int main()
{
//freopen("input.txt","r",stdin);
int i;
T=(node*)malloc(sizeof(node));
for(i=0;i<26;i++)
T->next[i]=NULL;
while(1)
{
gets(str);
if(strcmp(str,"")==0)
break;
sscanf(str,"%s %s",arr1,arr2);
Diction();
}
while(scanf("%s",str)!=EOF)
search();
return 0;
}另一种思路就是直接用快排+二分的组合,这样的使用方法也非经常见;在这个题目中用到了fgets,sscanf这两个函数。都是第一次用。还用了c语言库里面的qsort和bsearch。然后自己又写了一次二分;比写字典树难度还是小了非常多。非常多细节上还是把握的不好啊;
- 以下是ac的代码,直接调用库函数写的。
-
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
struct node //节点的结构体
{
char eng[12];
char fore[12];
};
node dictionary[maxn];
int cmp(const void *a,const void *b){ //比較函数
return strcmp(((node *)a)->fore,((node *)b)->fore);
}
int search(const void *a,const void *b){ //二分查找函数
return strcmp((char *)a,((node *)b)->fore);
}
int main()
{
//freopen("1.txt","r",stdin);
char english[30],forigen[20];
int count=0,flag;
node *p;
while(fgets(english,29,stdin)&&english[0]!='\n')
{
sscanf(english,"%s%s",dictionary[count].eng,dictionary[count].fore);
count++;
}
qsort(dictionary,count,sizeof(node),cmp);
while(scanf("%s",forigen)!=EOF)
{
p=NULL;
p=(node*)bsearch(forigen,dictionary,count,sizeof(node),search);
if(p)
printf("%s\n",p->eng);
else
printf("eh\n");
}
return 0;
}自己写得二分查找;
-
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
struct node //节点的结构体
{
char eng[12];
char fore[12];
};
node dictionary[maxn];
bool Cmp(node one, node two)
{
return strcmp(one.fore, two.fore) < 0;
}
int bsearch(char *s,int n) //二分查找
{
int mid,start,end;
start=0;end=n-1;
int flag=0;
while(start<=end)
{
mid=(start+end)/2;
flag=strcmp(s,dictionary[mid].fore);
if(flag==0)
return mid;
if(flag<0)
{
end=mid-1;
}
else
{
start=mid+1;
}
}
return -1;
}
int main()
{
//freopen("1.txt","r",stdin);
char english[30],forigen[20];
int count=0,flag;
node *p;
while(fgets(english,29,stdin)&&english[0]!='\n')
{
sscanf(english,"%s%s",dictionary[count].eng,dictionary[count].fore);
count++;
}
sort(dictionary,dictionary+count,Cmp);
while(scanf("%s",forigen)!=EOF)
{
flag=bsearch(forigen,count);
if(flag!=-1)
{
printf("%s\n",dictionary[flag].eng);
}
else
printf("eh\n");
}
return 0;
}在平时做题中还是要多积累。
- 总结:这个题目能够用多种思路去做,平时练习能够多去尝试一下,熟悉一下库函数。fgets,sscanf对输入格式的控制;qsort中cmp函数的格式。还用bsearch里面search函数的写法和格式,传递的參数。对于字典树在模板的基础上还要依据题意灵活处理,像这道题的话,设置一个參数表示结束就会非常方便;
- 标题不,在晴朗。。
poj 2804 字典 (特里 要么 快排+二分法)的更多相关文章
- POJ 2503 Babelfish(map,字典树,快排+二分,hash)
题意:先构造一个词典,然后输入外文单词,输出相应的英语单词. 这道题有4种方法可以做: 1.map 2.字典树 3.快排+二分 4.hash表 参考博客:[解题报告]POJ_2503 字典树,MAP ...
- poj 1328 Radar Installation(贪心+快排)
Description Assume the coasting is an infinite straight line. Land is in one side of coasting, sea i ...
- iOS常见算法(二分法 冒泡 选择 快排)
二分法: 平均时间复杂度:O(log2n) int halfFuntion(int a[], int length, int number) { int start = 0; int end = l ...
- Java基础进阶:APi使用,Math,Arrarys,Objects工具类,自动拆装箱,字符串与基本数据类型互转,递归算法源码,冒泡排序源码实现,快排实现源码,附重难点,代码实现源码,课堂笔记,课后扩展及答案
要点摘要 Math: 类中么有构造方法,内部方法是静态的,可以直接类名.方式调用 常用: Math.abs(int a):返回参数绝对值 Math.ceil(double a):返回大于或等于参数的最 ...
- STL函数库的应用第二弹——快排sort函数与结构体关键字排序
时隔20多天,本蒟蒻终于记起了他的博客园密码!!! 废话不多说,今天主题:STL快排函数sort()与结构体关键字排序 Part 1:引入和导语 首先,我们需要知道,algorithm库里有一些奇怪的 ...
- F#之旅4 - 小实践之快排
参考文章:https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/posts/fvsc-quicksort.html F#之旅4 - 小 ...
- 快排 快速排序 qsort quicksort C语言
现在网上搜到的快排和我以前打的不太一样,感觉有点复杂,我用的快排是FreePascal里/demo/text/qsort.pp的风格,感觉特别简洁. #include<stdio.h> # ...
- C++ 快排
// 进行一轮快排并返回当前的中间数 int getMiddle( int* arr, int low, int high ) { auto swaparr = [&]( int i, int ...
- 先贴上代码:Random快排,快排的非递归实现
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为主元,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序.值得注意的是, ...
随机推荐
- Codeforces Round #256 (Div. 2) A. Rewards
A. Rewards time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- JS window.open()财产
一. Window 对象 Window 对象是 JavaScript 顶级对象层次. Window 对象表示一个浏览器窗口或帧. Window 在对象 <body> 或 <frame ...
- Jenkins详细安装与构建部署使用教程(转)
Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能.Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括:1.持续的软件版本发布 ...
- Oracle使用并行建索引须要注意的问题
建索引时.我们为了建索引快.会加上并行,加上并行之后.此列索引就会是并行了. 訪问有并行度的索引时,CBO可能可能会考虑并行运行.这可能会引发一些问题,如在server资源紧张的时候用并行会引起更加严 ...
- [LeetCode]Word Ladder 最短距离字符串转换 (Dijkstra)
要求最短距离.采纳dijkstra查找节点之间的最短路径. 当心:假设是一个枚举字典22是否元素可以,如果转换,暂停. 提高:每串,带您历数它的字符值事件,对于的长度n一个字符串枚举n*26次要. 设 ...
- MVC 使用EF Code First数据迁移之添加字段
PM> add-migration 20161109 -Force 正在为迁移“20161109”搭建基架.此迁移文件的设计器代码包含当前 Code First 模型的快照.在下一次搭建迁移 ...
- 最常用的动态sql语句梳理Mybatis(转)
公司项目中一直使用Mybatis作为持久层框架,自然,动态sql写得也比较多了,最常见的莫过于在查询语句中使用if标签来动态地改变过滤条件了.Mybatis的强大特性之一便是它的动态sql,免除了拼接 ...
- opencv2使用形态学滤波对图像进行边缘及角点检測
#if !defined MORPHOF #define MORPHOF #include <opencv2/core/core.hpp> #include <opencv2/img ...
- 进程和线程之间的关系和区别 和 CPU牒
流程具有一定独立功能的程序关于某个数据集合上的一次执行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立执行的基本单位. 进 ...
- ThinkPad E530 Fedora 20 无线上网问题
它一直在使用 Fedora 家庭 Linux. 但它自带的无线网卡驱动似下一些问题,通常,有时连接,有时你不能. 经常搜索不到的家用无线路由器. 因为家里有网线所以一直没有在意.没什么事就折腾了一下. ...