我在数组中有很长的单词列表。有些短,有些长。我想过滤掉那些以数组中的单词开头的单词(这个“前缀”单词的长度可以设置为3个字符),并且同时以单词结尾。
让我们说第一个词是'车棚'。现在,如果阵列中还存在'car'和'port',我会得到一个匹配。但如果这个词是'carlsberg',我就不会得到匹配(因为'lsberg'可能不会是数组中现有的单词)。
结果最好是“前缀词,后缀词,整个词”。
我会考虑使用任何可以让我这样做的语言,尽管我自己主要是一个JavaScript人。
答案 0 :(得分:1)
我想知道trie是否会有所帮助,请参阅What is the most common use of the “trie” data structure?。
Perl有几个模块来构建它们:
其他听起来像是起点的地方是Ruby's Abbrev
模块:
#!/usr/bin/env ruby
require 'abbrev'
require 'pp'
pp %w[car port carport carlsberg].abbrev
# >> {"por"=>"port",
# >> "po"=>"port",
# >> "p"=>"port",
# >> "carpor"=>"carport",
# >> "carpo"=>"carport",
# >> "carp"=>"carport",
# >> "carlsber"=>"carlsberg",
# >> "carlsbe"=>"carlsberg",
# >> "carlsb"=>"carlsberg",
# >> "carls"=>"carlsberg",
# >> "carl"=>"carlsberg",
# >> "car"=>"car",
# >> "port"=>"port",
# >> "carport"=>"carport",
# >> "carlsberg"=>"carlsberg"}
答案 1 :(得分:0)
嗯,JavaScript中的天真实现是这样的:
function triples(words) {
var result = new Array();
for(var i=0; i<words.length; i++) {
for(var j=0; j<words.length; j++) {
var k = words.indexOf(words[i] + words[j]);
if(k != -1) {
result.push([words[i], words[j], words[k]]);
}
}
}
return result;
}
当前形式的函数需要所有单词的数组作为参数,并返回包含找到的单词三元组的数组数组(第一个元素是前缀,第二个元素是后缀,第三个元素是组合单词)。 / p>
答案 2 :(得分:0)
这样的事情:
#!/usr/bin/perl
use strict;
use warnings;
my @candidates=qw( carport Carsburg butterfly
buttercup Christmas wishlist carpface flyface buttface);
my @arr=<DATA>;
chomp @arr;
for my $i (3..6) {
foreach my $j (@candidates) {
my ($fp,$lp)=($1,$2) if ($j=~/(^.{$i})(.*$)/);
if($fp && $lp) {
my @hit1=grep(/^$fp/,@arr);
my @hit2=grep(/$lp$/,@arr);
print "candidate: $j\n start= @hit1 end= @hit2\n=====\n"
if (scalar @hit1 && scalar @hit2);
}
}
}
__DATA__
car
port
wish
list
Christ
mas
butter
cup
fly
face
butt
输出:
candidate: carport
start= car end= port
=====
candidate: flyface
start= fly end= face
=====
candidate: wishlist
start= wish end= list
=====
candidate: buttface
start= butter butt end= face
=====
candidate: butterfly
start= butter end= fly
=====
candidate: buttercup
start= butter end= cup
=====
candidate: Christmas
start= Christ end= mas
答案 3 :(得分:0)
这是一个O(n + 2m)
的Perl解决方案:
use warnings;
use strict;
use Data::Dumper;
my @words = qw(car carport carlsberg cartographer airport photographer);
my @ends = qw(car port air grapher);
my $ends_re = join '|' => @ends;
my @matches = map {/^($ends_re).*($ends_re)$/ ? [$1, $_, $2] : ()} @words;
print Dumper \@matches;
打印:
$VAR1 = [
[
'car',
'carport',
'port'
],
[
'car',
'cartographer',
'grapher'
],
[
'air',
'airport',
'port'
]
];
答案 4 :(得分:0)
我会做类似的事情:
<?php
$words = array('experts', 'exchange', 'expert', 'sexchange');
// build trie
$t = array();
foreach ($words as $word)
{
$n = &$t;
for ($i = 0; $i < strlen($word); ++$i)
{
$c = $word[$i];
if (!isset($n[$c])) $n[$c] = array();
$n = &$n[$c];
}
$n['.'] = true;
}
$word = 'expertsexchange';
$n = $t;
for ($i = 0; $i < strlen($word); ++$i)
{
$c = $word[$i];
if (isset($n['.']))
{
$o = $t;
for ($j = $i; $j < strlen($word); ++$j)
{
$d = $word[$j];
if (!isset($o[$d])) break;
$o = $o[$d];
}
# found match
if ($j == strlen($word) && isset($o['.']))
{
echo substr($word, 0, $i).",".substr($word,$i).",".$word."\n";
}
}
if (isset($n[$c]))
{
$n = $n[$c];
}
else
break;
}
?>
Results:
expert,sexchange,expertsexchange
experts,exchange,expertsexchange
我是当场写的,所以它可能无法正常工作。但我们的想法是构建一个前缀树并逐步完成它。每次找到前缀(通过'。'表示)时,再次从树顶部继续查看是否可以从该点找到后缀。假设您在前缀和后缀之间不需要任何内容。