【问题标题】:Finding a loose match for a string in arraylist在arraylist中查找字符串的松散匹配
【发布时间】:2011-03-08 23:19:27
【问题描述】:

我有一个巨大的数组列表,其中包含 1000 个条目,其中一个条目是“世界”。而且,我有一个词“大世界”。我想在arraylist中得到与“world”匹配的“big world”这个词。

最经济有效的方法是什么?我不能使用数组列表的 .contains 方法,如果我遍历所有 1000 个条目并通过模式匹配它们,那么在性能方面将非常昂贵。我正在为此使用 Java。

您能告诉我什么是最好的方法吗?

干杯, J

【问题讨论】:

  • 定义“松散”匹配。一个字符串必须是另一个字符串的子串吗? “心”和“耳”会匹配吗?这些是英文单词/短语吗?如果我们要求你摆脱 ArrayList,你能做到吗?
  • 是的,你的权利! “心”字与“耳”相配。我可以灵活地使用任何类型的数据结构!
  • 再澄清一点:1000 个字符串的集合是静态的吗?您究竟想如何进行子字符串匹配?给定一个单词 U,你想在数组列表中找到一个单词 V,使得 V 是 U 的子串?如果 U 是其他 V' 的子字符串,那也是匹配吗?

标签: java algorithm substring


【解决方案1】:

假设您不知道 arraylist 元素的内容。你将不得不遍历整个数组列表。

遍历数组列表会花费你 O(n)。

对arraylist 进行排序对您没有帮助,因为您正在谈论在一组字符串中搜索一个字符串。并且仍然排序会更昂贵。 O(nlogn)

【讨论】:

    【解决方案2】:

    如果您必须重复搜索列表,使用Collectionssort()binarySearch() 方法可能有意义。

    附录:正如@user177883 所述,O(n log n) 排序的成本必须与后续 O(log n) 搜索的收益进行权衡.

    单词“heart”匹配[word]“ear”。

    由于完全匹配是不够的,所以这种方法是不够的。

    【讨论】:

    • 排序会比搜索更昂贵。
    • 我可以这样做,但是如果您看到 binarySearch 被编写为返回完全匹配。虽然我可能会编写一个自定义的 Comparator,但可能很难确定松散匹配。
    • 当用户找到该值时,如何知道用户是否想停止。什么是用户想要找到所有出现的字符串。那么你将不得不使用许多二进制搜索。每次你发现一个事件,你把它从 adt 中删除,然后你再做一次二分查找,最坏的情况你可能会做 n 次二分查找。你最坏的情况复杂度将是 2nlogn。与顺序搜索相比,这非常有效。
    • 一种廉价的二分搜索将使检查候选字符串中的每个单词的精确匹配成为可能。正如@Moron 所说,澄清你的匹配标准可能会很有用。
    【解决方案3】:

    您可以将ArrayList 的每个元素拆分为单词,并在找到其中一个时立即停止。

    我想根据您的个人资料,您使用 Java 开发,使用 Lucene 您可以轻松地做类似的事情

    public class NodesAnalyzer extends Analyzer {   
        public TokenStream tokenStream(String fieldName, Reader reader) {
    
            Tokenizer tokenizer = new StandardTokenizer(reader)
            TokenFilter lowerCaseFilter = new LowerCaseFilter(tokenizer)
            TokenFilter stopFilter = new StopFilter(lowerCaseFilter, Data.stopWords.collect{ it.text } as String[])
            SnowballFilter snowballFilter = new SnowballFilter(stopFilter, new org.tartarus.snowball.ext.ItalianStemmer())
    
            return snowballFilter
        }   
    }
    
        Analyzer analyzer = new NodesAnalyzer()
    
        TokenStream ts = analyzer.tokenStream(null, new StringReader(str)); 
        Token token = ts.next()
    
        while (token != null) {
           String cur = token.term()
           token = ts.next();
        }
    

    注意:这是我从个人项目中复制的 Groovy 代码,因此您必须翻译 Data.stopWords.collect{ it.text } as String[] 之类的内容才能与普通 Java 一起使用

    【讨论】:

    • Lucene 非常适合这种情况,尤其是当它超过 1000 个字时。
    【解决方案4】:

    我有一个非常相似的问题。

    使用if/else if 语句解决了这个问题。

    if (myArrayList.contains(wordThatIsEntered) 
        && wordThatCantBeMatched.equals(wordThatIsEntered)) {
    
        Toast.makeText(getApplicationContext(), 
        "WORD CAN'T BE THE SAME OR THAT WORD ISN'T HERE", 
        Toast.LENGTH_SHORT).show(); 
    } 
    
    else if (myArrayList.contains(wordThatIsEntered)) {
    
        Toast.makeText(getApplicationContext(), 
        "FOUND THE EXACT WORD YOU ARE LOOKING FOR!", 
        Toast.LENGTH_SHORT).show(); 
    }
    

    【讨论】:

      猜你喜欢
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-30
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多