检测字符串是否包含多个单词的更好方法

时间:2013-09-19 01:46:58

标签: java string substring contains

你好伙伴们!我正在尝试创建一个程序,以尽可能快地检测字符串中是否有多个单词,如果是,则执行一个行为。最好,我希望它能够检测这些单词的顺序,但只有这样才能快速完成。到目前为止,这就是我所做的:

if (input.contains("adsf") && input.contains("qwer")) {
    execute();          
}

正如您所看到的,为多个单词执行此操作会变得很烦人。这是唯一的方法还是有更好的方法来检测多个子串?有没有办法检测订单?

7 个答案:

答案 0 :(得分:33)

我会用以下词语创建一个正则表达式:

Pattern pattern = Pattern.compile("(?=.*adsf)(?=.*qwer)");
if (pattern.matcher(input).find()) {
    execute();
}

有关详细信息,请参阅此答案:https://stackoverflow.com/a/470602/660143

答案 1 :(得分:9)

您可以使用数组:

String[] matches = new String[] {"adsf", "qwer"};

bool found = false;
for (String s : matches)
{
  if (input.contains(s))
  {
    execute();
    break;
  }
}

这是您发布的有效但更易于维护的效率。寻找更有效的解决方案听起来像微优化,在被证明是有效的代码瓶颈之前应该被忽略,无论如何使用巨大的字符串集,解决方案可能是一个特里。

答案 2 :(得分:2)

在Java 8中,您可以做到

String[] searchFor= {"asdf", "qwer"};
String input = "asdf qwer";
public static boolean containsItemFromArray(String inputString, String[] items) {
    return Arrays.stream(input).allMatch(searchFor::contains);
}

答案 3 :(得分:1)

如果要查找很多子字符串,那么正则表达式可能不会有太大帮助,所以最好将子字符串放在列表中,然后迭代它们并调用{{1在每一个上。这将返回找到子字符串的位置的input.indexOf(substring)索引。如果将每个结果(除了-1,这意味着未找到子字符串)抛出到int(其中TreeMap是键,子字符串是值),那么您可以检索它们通过在地图上调用index来顺序完成。

keys()

答案 4 :(得分:1)

使用树结构来保存每个代码点的子字符串。这消除了

的需要

请注意,仅当针头组几乎不变时,这才有效。如果有单独的子串的添加或删除,这并不是低效的,但是每次将不同的初始化排列到树结构中的初始化肯定会慢一些。

StringSearcher

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

class StringSearcher{
    private NeedleTree needles = new NeedleTree(-1);
    private boolean caseSensitive;
    private List<Integer> lengths = new ArrayList<>();
    private int maxLength;

    public StringSearcher(List<String> inputs, boolean caseSensitive){
        this.caseSensitive = caseSensitive;
        for(String input : inputs){
            if(!lengths.contains(input.length())){
                lengths.add(input.length());
            }
            NeedleTree tree = needles;
            for(int i = 0; i < input.length(); i++){
                tree = tree.child(caseSensitive ? input.codePointat(i) : Character.toLowerCase(input.codePointAt(i)));
            }
            tree.markSelfSet();
        }
        maxLength = Collections.max(legnths);
    }

    public boolean matches(String haystack){
        if(!caseSensitive){
            haystack = haystack.toLowerCase();
        }
        for(int i = 0; i < haystack.length(); i++){
            String substring = haystack.substring(i, i + maxLength); // maybe we can even skip this and use from haystack directly?
            NeedleTree tree = needles;
            for(int j = 0; j < substring.maxLength; j++){
                tree = tree.childOrNull(substring.codePointAt(j));
                if(tree == null){
                    break;
                }
                if(tree.isSelfSet()){
                    return true;
                }
            }
        }
        return false;
    }
}

NeedleTree.java

import java.util.HashMap;
import java.util.Map;

class NeedleTree{
    private int codePoint;
    private boolean selfSet;
    private Map<Integer, NeedleTree> children = new HashMap<>();

    public NeedleTree(int codePoint){
        this.codePoint = codePoint;
    }

    public NeedleTree childOrNull(int codePoint){
        return children.get(codePoint);
    }

    public NeedleTree child(int codePoint){
        NeedleTree child = children.get(codePoint);
        if(child == null){
            child = children.put(codePoint, new NeedleTree(codePoint));
        }
        return child;
    }

    public boolean isSelfSet(){
        return selfSet;
    }

    public void markSelfSet(){
        selfSet = true;
    }
}

答案 5 :(得分:0)

这是经典的面试和CS问题。

Robin Karp算法通常是人们在采访中首先谈到的。基本思想是,当您遍历字符串时,会将当前字符添加到哈希中。如果哈希值与您的匹配字符串之一的哈希值匹配,则说明您可能有一个匹配项。这样可以避免来回扫描到您的匹配字符串中。 https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm

该面试问题的其他典型主题是考虑特里结构以加快查找速度。如果您有大量的匹配字符串,则必须始终检查大量的匹配字符串。特里结构更有效地进行检查。 https://en.wikipedia.org/wiki/Trie

其他算法是:  -Aho–Corasick https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm  -Commentz-Walter https://en.wikipedia.org/wiki/Commentz-Walter_algorithm

答案 6 :(得分:0)

我认为一种更好的方法是这样的,在这里我们可以将多个值添加为一个字符串,并通过函数索引来验证索引

String s = "123"; 
System.out.println(s.indexOf("1")); // 0
System.out.println(s.indexOf("2")); // 1 
System.out.println(s.indexOf("5")); // -1