网络上看到腾讯的题(强行PHP解答)

2 篇文章 0 订阅
1 篇文章 0 订阅

看到腾讯的这个面试题,这个题使用sed或awk 估计效率会更高,但我忍不住想PHP解答一下

思路是 先建索引文件(优化效率),之后传参 分解参数,找相应的索引文件(记录行号和单词号)
题:
我们碰到了大麻烦,一个新来的传教士惹恼了上帝,上帝很愤怒,要求我们把圣经(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

解题:
bbe.txt文件咱们没有  想像成是 空格 隔开的算了

hello123 hello tim jason
woaini1 tianjianxiong333 hh aaa

/* 此文件用于根据bbe.txt文件对所有单词创建索引,相当于一次预处理 */ 
ini_set('display_errors','on');
set_time_limit(0);
$file = file($src); // 数组
foreach($file as $i => &$ls){
	$a = explode(" ",$ls);
	$len = count($a);
	if ($len > 0){
		for($j=0;$i<$len;$j++){
			$data = "此单词".$a[$j]."在".($i+1)."行,".($j+1)."列";
			$key = md5(trim(strtolower($a[$j])));
			file_put_contents($key,$data);
		}
	}
	//echo $i.". > ".$ls.'<br />';
}


example.php:

#!/usr/local/bin/php -q 
<?php

set_time_limit(0); 

$getkey=empty($argv[1]) ? $_REQUEST['k'] : $argv[1];

$arr = explode(",",$getkey);

$len = count($arr);

if($len > 0){
	for($i=0;$i<$len;$i++){
		echo getKey($arr[$i])."\n";
	}
}

functuion getKey($key){
	$str = "没有找到此单词[".$key."]";
	if($key){
		$fc = md5($key);
		$str = file_get_contents($fc));
	}
	return $str;
}
?>


记得把 example.php  755 一下

别人的方法:
1、使用ascii码,判断字符所在范围
2、只要扫描一遍字符即可,复杂度为O(N)
3、利用了php string{$i} 的特性,取字符串内任一字符
4、todo:改为fgetc版本,可以完全不需要使用以上php特性
5、字符串匹配算法:http://wendell07.blog.hexun.com/14112681_d.html,目前看来最快的方法:Sunday,由于本题是单词匹配,问题更简单,只要找到头尾……

$word = $argv[1];
$lines = 0;

$handle = @fopen("bbe.txt", "r");
if ($handle) {
    while (!feof($handle)) {
        $line = fgets($handle, 4096);
        $local = local_word($line, $word);
        $lines++;
        if( !empty($local) ){
            echo "$lines,".implode(' ',$local)."\n";
        }
    }
    fclose($handle);
}

function local_word($line, $word){
    $local = array();
    $local_length = 1;
    $word_length = strlen($word);

    for($i = 0; ( $char = $line{$i} ) !== ''; $i++ ){
        // 单词最后一个字符必定不是符号,且必有一个符号结尾,此计为一个新词
        if( !is_symbel( $line{ $i-1 } ) && is_symbel($char) ){
            $local_length++;
        }    

        if( $char === $word[0] && // 如果第一个字符相同
            is_symbel( $line{ $i-1 } ) && // 且为单词开始
            is_symbel( $line{ $i+$word_length }) // 单词结尾应该为符号
        ){
            // 进入验证单词模式,一个一个字符比对
            for($j = 1; ($w_char = $word{$j}) !== ''; $j++ ){
                // 遇到单词字符不匹配
                if( $w_char != $line{ $i+$j } ){
                    $i += $j;
                    break;
                }
                // 如果单词比对完全正确
                if( $j == ($word_length-1) ){
                    //echo "$line_length, $word_length\n";
                    $local[] = $local_length;
                }
            }
        }
    }
    return $local;
}

function is_symbel($char){
    $asc = ord($char);
    return !( (48 <= $asc && $asc <= 57) ||
              (65 <= $asc && $asc <= 90) ||
              (97 <= $asc && $asc <= 122) );
}


原文地址:

http://www.xiaot.net/post/HaoQiGuaiDeFenJieQi.html

来自 小田 的博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值