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],首先任意选取一个数据(通常选用数组的第一个数)作为主元,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序.值得注意的是, ...
随机推荐
- PL/SQL 游标的使用
游标的使用 ①游标概念 为了处理SQL 语句,ORACLE 必须分配一片叫上下文( context area )的区域来处理所必需的信息, 当中包含要处理的行的数目.一个指向语句被分析以后的表示 ...
- char *详细指针
我前段时间写的char*和char[]差额.今char*做一个更深入的了解 1:char像指针和其他指针,也定义一个地址,例如int*它定义了一个堆栈,4字节,char*之,现在写一段代码 #incl ...
- 注意事项: Solr设备 Hello World
试用 Solr-4.10.2 一 shards, 这两款机器 一是垃圾 rm -r example/solr/collection1/data/* 启动一个 node cd example java ...
- Android-管理Activity生命周期 -开始一个Activity
很多程序都是从main()方法开始启动的,和其他程序不同,android是在activity生命周期的特定状态的特定回调方法中初始化代码的.activity启动和销毁的时候都用很多回调方法. 这里将要 ...
- php+sqlite cms
1 phpSQLiteCMS 最新版本 phpSQLiteCMS 2.0.4 http://phpsqlitecms.net/ 2 taoCMS 最新版本 [2.5Beta5下载地址] 需要php ...
- 浅谈web网站架构演变过程(转)
前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变. 该系统具备的功能: 用户模块:用户注册和管理 商品模块:商品展示和管理 交易模块:创建交易和管理 阶 ...
- 求n阶勒让德多项式
Time Limit: 1 Sec Memory Limit: 128 MB Submit: 161 Solved: 105 [Submit][Status][Web Board] Descrip ...
- vb.net它SqlHelper制备及应用
上次文章中说到.对于一个项目来说.SqlHelper是一个非常重要的类. 在正在构造的机房收费系统中.有大量的操作数据库的操作. 现在.把反复的代码所有拿出来,就形成了SqlHelper类.这个Sql ...
- IIS安装asp组件:JMail 邮件收发组件
JMail简介 jmail是一种服务器端的邮件发送组件,和个人用的客户端邮件软件不一样的.jmail是在服务器上给程序用来发邮件用的,除了软件编程人员,其他人一般平常用不上. jmail是一个第三方邮 ...
- java提高篇(十四)-----关键字final
在程序设计中,我们有时可能希望某些数据是不能够改变的,这个时候final就有用武之地了.final是java的关键字,它所表示的是"这部分是无法修改的".不想被改变的原因有两个:效 ...