1、我们碰到了大麻烦,一个新来的传教士惹恼了上帝,上帝很愤怒,要求我们把圣经(bbe.txt)背熟,直至他说哪个单词,我们就要飞快的回答出这个单词在第几行第几个单词位置。听说你是个优秀的程序员,那么髟助我们完成这个不可能的任务吧。
要求如下:
1)/myworks/example/bbe.txt,98版本英文圣经一本
2)输入部分要求如下:php ./example.php [单词]
3)输出部分如下:[单词] 1,2 2,4 5,6 表示:此单词在1行2列(第二个单词),2行4列...
说明:
1)此文本4MB之巨...
2)单词的含义:由英文字母(大小写),数字(0-9)组成的串
3)提供给你的机器OS为ubuntu 9.10,内存只有1G,而且,很不幸的,其中700M用来做了别的
4)上机考试不允许上网,但我装了man文档以及读取CHM以及PDF的阅读器,在电脑的桌面的CHM文件夹中,有相应的PHP参考手册
5)算法复杂度要求不能大于O(N^2)(就是N的平方)
6)什么?PHP低效且用起来不顺手,好的,你可以用别的语言来实现。但注意:提供给你的机器上只有python 2.4/perl 5.8/gcc[g++] 4.1
最后一道题,我用了建文件索引的方法,似乎也没违反题的规则,关于索引那里,还可以继续深入优化。
-
<?php /* 此文件用于根据bbe.txt文件对所有单词创建索引,相当于一次预处理 */ ini_set('display_errors','on'); set_time_limit(0); //行号 $row = 1; //单词计数 $space = 0; //单词 $str = ''; //单词数组 $strs = array(); $fp = fopen('./bbe.txt','r'); //读取bbe.txt文件 while(!feof($fp)){ //每次读1字节 while($ch = fread($fp,1)){ //如果读到的是换行,换行计数加1 if( $ch == "/n" || $ch == "/r/n" ){ $row++; $space=0; } //如果读到的是空格,单词计数加1,并且把这个单词按照单词名放进hash,值为行,列。 elseif( $ch == " " || $ch == "/n" || $ch == "/r/n" ){ $space++; $str = strtolower($str); if(!isset($strs[$str])) $strs[$str] = ''; $strs[$str] .= ' '.$row.','.$space; $str = ''; } //ascII范围不在A-Z或a-z之间的丢弃 elseif((ord($ch) < 65 || ord($ch) > 90) && (ord($ch) < 97 || ord($ch) > 122)){ //echo $ch; continue; } else{ $str .= $ch; } } } fclose($fp); //处理hash foreach($strs as $sk => $sv){ $fc = strtolower(substr($sk,0,1)); $nstrs[$fc][$sk] = $sv; } //排序并写入文件散列 foreach($nstrs as $ns => $nv){ $nstrs[$ns] = $nv; file_put_contents('./indexs/'.$ns.'.txt',serialize($nstrs[$ns]),FILE_APPEND); } die('索引创建完毕!');
-
<?php /* 此文件用来查询单词,调用格式为http://url/searchStr.php?searchKey=mysql */ $key = strtolower($_GET['searchKey']); $fc = strtolower(substr($key,0,1)); $arrayVal = unserialize(file_get_contents('./indexs/'.$fc.'.txt')); isset($arrayVal[$key])?print($key.'的位置序列:'.$arrayVal[$key]):print('没有找到此单词!'); ?>