-2

给定一个像“我正在搜索文本”这样的短语和一个包含单词列表的文本文件。

我必须找到文本文件中是否存在单词的每个组合。

例如,我必须搜索出现“我”、“我是”、“我正在搜索”、“我正在搜索”、“正在搜索”等。

我更喜欢用 perl 编写它,我需要一个运行速度更快的最佳解决方案。

示例文本文件:

I \n
am searching \n
Text \n
searching for \n 
searching for a \n
for searching       ---> my program should not match this 
etc
4

2 回答 2

1

下面的代码打印出您想要匹配的所有 sub_phrases。

$phrase = 'I am searching for a text';
$\ = "\n";

@words = ();
print "Indices:";
while( $phrase =~ /\b\w+\b/g ) {
    push @words, {word => $&, begin => $-[0], end => $+[0]};
}

$num_words = $#words + 1;
print 'there are ', $num_words, ' words';


for( $i=0; $i<$num_words; $i++ ) {
    for( $j=$i; $j<$num_words; $j++ ) {
        ($start,$finish) = ($words[$i]->{begin}, $words[$j]->{end});
        $sub_phrase = substr $phrase, $start, $finish-$start;
        print "$i-$j: $sub_phrase";
    }
}

一些解释:

  1. $\ 只是为了让“打印”更容易
  2. $phrase - 使用您的示例
  3. @words 是对记录的引用数组
  4. 每条记录都是单词本身的哈希,索引到单词的开头和结尾
  5. 我有一个正则表达式,我正在迭代。我正在寻找单词边界、1 个或多个单词字符和单词边界。
  6. $+ 和 $- 是最后一个 RE 匹配索引的特殊变量
  7. $& 是最后一个 RE 匹配的特殊变量
  8. 然后我有一个嵌套循环:$i,外部循环变量是第一个单词。$j 是最后一句话。这涵盖了所有的组合。
  9. 我正在计算 $sub_phrase 从第一个单词的开头到最后一个单词的结尾。

为了完成您的练习,您希望将所有 sub_phrase 保存到一个数组中(而不是 'print' 执行 'push' 到 @permutations)。然后遍历您的文本文件,并为每一行尝试匹配每个排列。

于 2012-10-25T14:53:10.083 回答
1

您可以构造一个适用于所有这些情况的表达式。下面,我将展示如何在 Perl 中构建一个(尽管您可以将产品用于您的目的)。

use List::Util qw<reduce>;

our ( $a, $b );

my $regex       
    = "\n^\n( "
    . join( "\n| "
    , @{( reduce { 
            my $r = ref( $a ) ? $a : [ "$a " ];
            my $s = $r->[0];
            [ "$b (?> [ ] $s)?", @$r ] 
        } 
        reverse split ' ', 'I am searching for a text'
        )}
    )
    . "\n)\n\\s*\n\$"
    ;
say join( "\n# ", split "\n", $regex );

# ^
# ( I (?> [ ] am (?> [ ] searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?)?)?
# | am (?> [ ] searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?)?
# | searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?
# | for (?> [ ] a (?> [ ] text )?)?
# | a (?> [ ] text )?
# | text 
# )
# \s*
# $

map { say foreach m/$regex/xo } <DATA>;
  • 我已经添加了锚点,因为您指出它应该与整行匹配。
  • 完成的正则表达式中有空格,但它/x用来忽略它们。这就是为什么我们用 指定空间[ ]
  • 分组表示法(?>...)是 non-capturing 的一种变体(?:...),但失败的速度要快得多。请参阅http://perldoc.perl.org/perlre.html#(%3f%3epattern)
  • List::Util::reduce
于 2012-10-25T15:10:35.103 回答