2010-09-01 88 views
2

我有一個數組中的單詞的長列表。有些短暫,有些長。我想過濾掉那些以數組中的單詞開頭的單詞(這個「前綴」單詞的長度可以設置爲3個字符),並且同時以它的單詞結尾。如何搜索以同一陣列中的其他單詞開頭和結尾的單詞?

假設第一個詞是'carport'。現在,如果陣列中存在'car'和'port',我會得到一個匹配。但如果這個詞是'carlsberg',我不會得到一個匹配(因爲'lsberg'可能不會是數組中存在的單詞)。

結果最好會出現爲「前綴詞,後綴詞,整個詞」。

我會考慮使用任何語言,可以讓我這樣做,雖然我主要是一個JavaScript的人自己。

+2

你有嘗試過嗎?你可以發佈你到目前爲止?謝謝。 – alex 2010-09-01 00:56:21

+0

你說「任何語言」 - 這是一個Web應用程序?如果是這樣,您使用的服務器技術是否可以訪問PHP/PERL/ASP? 如果這只是一個頁面重新加載,你可能會得到更好的性能,做它的服務器端。 如果你能提供更多的信息,我會盡我所能爲你解決方案:) – Basic 2010-09-01 01:02:36

+0

這將是一個「運行一次」的東西來生成一個新的文件。 昨晚我只嘗試了一些regexp,但是想和你們一起檢查一下,是否有任何優雅的解決方案,不管語言如何(我知道某些語言比其他類型的任務更適合)。到目前爲止(快速!)的反應令人驚訝,非常感謝! – naton 2010-09-01 11:50:52

回答

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; 
} 

在其當前形式的功能需要的所有單詞作爲參數陣列,並返回包含所找到的字三元數組的數組(第一元素是前綴,第二個元素是後綴,第三個元素是組合詞)。

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 
+0

雖然在該列表中有「車庫」(和其他「組合」詞語),但我認爲你已經接近我所追求的目標。也許篩選出多個開始和結束的匹配?我正在考慮在大量文本上使用這個過濾器,甚至可能是某種字典,所以我想每個啓動字都必須出現? – naton 2010-09-01 12:08:31

+0

我不知道我明白。你是說你在「__DATA」下面添加了「carport」嗎?如果你想要這種類型的過濾基於單個列表而不是兩個(我寫它的方式),它是稍微不同的邏輯。 – dawg 2010-09-01 15:38:46

+0

對不起,延遲迴復..是的,一個列表是我的目標。印度語可能是某種詞彙的詞彙,用於查找由列表中的其他詞組成的詞。 – naton 2010-11-10 14:31:38

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"} 
0

這裏我SA Perl的解決方案,O(n + 2m)

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' 
     ] 
    ]; 
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 

我寫在了當場,所以它可能無法正常工作完全正確。但是,這個想法是建立一個前綴樹,並通過它。每當你找到一個前綴(用'。'表示),從樹的頂部再次繼續,看看你是否可以從這一點找到後綴。這假定你不需要前綴和後綴之間的任何東西。

相關問題