【问题标题】:Need string matching algorithm需要字符串匹配算法
【发布时间】:2013-06-26 08:30:38
【问题描述】:

数据:

x.txt,简单的文本文件(大约 1 MB) y.txt 字典文件(大约 10 万个单词)。

需要查找 y.txt 中的任何单词/s 是否存在于 x.txt 中。

需要一种算法消耗更少的执行时间和首选语言。

PS:请推荐除 BRUTE FORCE METHOD 之外的任何算法。

我需要模式匹配而不是精确的字符串匹配。

例如:

x.txt : "The Old Buzzards 于 4 月 27 日解散"

Y.txt : "建立"

输出应该是:在 X.txt 中找到建立:第 1 行

谢谢。

【问题讨论】:

  • 这与正则表达式无关...
  • 定义蛮力方法..
  • Sets? (实现实际上取决于字典是否是静态的,以及您是否提供各种输入文本文件或其他方式)。
  • 字典文件将随着时间的推移而增长(更新),是的,我提供了多个输入文件。
  • BRUTE FORCE:将所有模式的字符与文本的每个字符进行比较,直到第一次失败(如果你之后比较那只是愚蠢的)。换句话说,您对文本中的字符进行了循环,并且您尝试每个模式直到它们失败,或者您不会从模式或连续成功或失败的比较中学到任何东西。

标签: regex string matching


【解决方案1】:

我不清楚你是需要这个来完成工作还是在家工作。如果您需要它来完成工作,那么:

#!/usr/bin/bash
Y=`cat y.txt | tr '\n' '|'`
echo "${Y%|}"
grep -E "${Y%|}" x.txt
if [ "$?" -eq 0 ]
then
    echo "found"
else
    echo "no luck"
fi

当您从文件中吸取所有模式,构建正则表达式(回显显示正则表达式)然后将其交给grep 时,这很难被击败,后者会为您构建一个有限状态自动机。这会飞起来,因为它最多比较文本中的每个字符一次。如果是家庭作业,那么我建议你参考 Cormen 等人的“算法简介”,或者龙书的前几章,这也将解释我刚才所说的。

忘了补充:y.txt 应该每行包含一个模式,但作为一个很好的副作用,你的模式不必是单个单词。

【讨论】:

  • 不是作业。我正在为服务器开发应用程序。而在应用方面,在y.txt或字典文件中,每个单词之间没有关系,因此无法构造通用的正则表达式。
  • 上述程序无法运行,因为 grep 参数有限制。它抛出以下错误“参数列表太长”
  • 在这种情况下,探索 grep 的 -f (--file) 选项。将您的模式转储到文件中,每行一个模式,效果与上面的代码相同。应该能解决问题。
【解决方案2】:

假设,您的标准库中有任何Set 实现,这里有一些伪代码:

dictionary = empty set

def populate_dict():
    for word in dict_file:
        add(dictionary, word)

def validate_text(text_file):
    for word in text_file:      ### O(|text_file|)
        if word in dictionary:  ### O(log |dictonary|)
            report(word)

populate_dict()
every_now_and_then(populate_dict)

这会给你O(t * log d) 而不是蛮力O(t * d) 其中td 分别是输入文本文件和字典的长度。我不认为任何更快的事情都是可能的,因为您无法比O(t) 更快地读取文件,也无法比O(log d) 更快地搜索。

【讨论】:

    【解决方案3】:

    这是我想了很久的搜索算法。 基本上算法分两步。

    在第一步中,y.txt 中的所有单词都被插入到树中。树中从根到叶的每条路径都是一个词。叶子是空的。

    例如,单词 dog 和 day 的树如下。

    <root>--<d>-<a>-<y>-<>
              \-<o>-<g>-<>
    

    算法的第二部分是向下搜索。当你到达一片空的叶子时,你就找到了一个词。

    Groovy 中的实现,如果需要更多 cmets,请询问

    //create a tree to store the words in a compact and fast to search way
    //each path of the tree from root to an empty leaf is a word
    def tree = [:]
    new File('y.txt').eachLine{ word->
        def t=tree
        word.each{ c ->
            if(!t[c]){
                t[c]=[:]
            }
            t=t[c]
        }
        t[0]=0//word terminator (the leaf)
    }
    println tree//for debug purpose
    //search for the words in x.txt
    new File('x.txt').eachLine{ str, line->
        for(int i=0; i<str.length(); i++){
            if(tree[str[i]]){
                def t=tree[str[i]]
                def res=str[i]
                def found=false
                for(int j=i+1; j<str.length(); j++){
                    if(t[str[j]]==null){
                        if(found){
                            println "Found $res at line $line, col $i"
                            res=str[j]
                            found=false
                        }
                        break
                    }else if(t[str[j]][0]==0){
                        found=true
                        res+=str[j]
                        t=t[str[j]]
                        continue
                    }else{
                        t=t[str[j]]
                        res+=str[j]
                    }
                    found=false
                }
                if(found) println "Found $res at line $line, col $i"//I know, an ugly repetition, it's for words at the end of a line. I will fix this later
            }
        }
    }
    

    这是我的 y.txt

    dog
    day
    apple
    daydream
    

    和x.txt

    This is a beautiful day and I'm walking with my dog while eating an apple.
    Today it's sunny.
    It's a daydream
    

    输出如下:

    $ groovy search.groovy
    [d:[o:[g:[0:0]], a:[y:[0:0, d:[r:[e:[a:[m:[0:0]]]]]]]], a:[p:[p:[l:[e:[0:0]]]]]]
    Found day at line 1, col 20
    Found dog at line 1, col 48
    Found apple at line 1, col 68
    Found day at line 2, col 2
    Found daydream at line 3, col 7
    

    这个算法应该很快,因为树的深度不依赖于 y.txt 中的单词数。深度等于y.txt中最长单词的长度。

    【讨论】:

      猜你喜欢
      • 2018-08-03
      • 1970-01-01
      • 2013-12-24
      • 2016-07-19
      • 2021-11-06
      • 2012-07-24
      • 2010-09-08
      • 2013-07-02
      • 1970-01-01
      相关资源
      最近更新 更多