前些日子有朋友去百度面试,带回来道面试题。颇为有趣,一年多没写过代码了。最近正寻思做点什么。正好从这个题开始学习算法吧。
题目如下:
有一个2G的文件,里面全是单词,想办法把所有的变位词找出。例如:stop和tops。
(写这个记录的时候我已经开始做这个题目有些时间了。也再次拿起了《编程珠玑》<这次看的是第二版了>,发现不那么ACM的算法题基本都出自Pearls)
初步想法:
1. 2G的大文件应该是不能内存操作的,但是可以尝试下使用内存映射文件直接排序。<暂时未深入去想>
2. 外部排序算法:翻书了,归并。
3. 我的思路:单词都是ASCII码,所以
第一步:单词累加,和一样,并且长度一样的单词是相同变位词的可能性就很大了。按照这个记录结果。
第二步:在前面的每个结果内,把单词内的字母排序,然后strcmp,相同的就是变位词。
Pearls的解答:
1. 单词内字母排序
2. 按照第一步的结果排序单词
3. 按顺序输出即为变位词。
我的看法:内存处理很快,不适合多核,没考虑怎么处理大文件。
不过我也没考虑大文件,但是我觉得我的想法可以多核并发,但是有个文件,磁盘I/O那么慢,有必要多核吗?有待后面测试。
准备工作:
首先要生成字典文件。我找了全套Harry potter的英文TXT下载。取了前四集作为输入,生成了我初步测试文件。 Harry Potter生成的字典文件大概2.5M左右。
Perl脚本如下:
sub read_lines($$){
my $filename = shift;my $outfilehandle = shift;open IN_FILE, "<$filename" or die("Could not open $filename");while (1){my $line = <IN_FILE>;
if (not defined($line)){ last;}
chomp($line);
my @info = split / /, $line;my $num = @info;
my $i = 0;
for ($i = 0; $i < $num; $i++){my $word = $info[$i];
$word =~ /(/w+)/;$word = $1;$word =~ tr/A-Z/a-z/;print $outfilehandle "$word/n";}}close(IN_FILE);
}open OUT_FILE, ">dict.txt" or die ("Could not create out_struct.txt");read_lines("1text.txt", OUT_FILE);
read_lines("2text.txt", OUT_FILE);
read_lines("3text.txt", OUT_FILE);
read_lines("4text.txt", OUT_FILE);
close(OUT_FILE);