你好伙伴们!我正在尝试创建一个程序,以尽可能快地检测字符串中是否有多个单词,如果是,则执行一个行为。最好,我希望它能够检测这些单词的顺序,但只有这样才能快速完成。到目前为止,这就是我所做的:
if (input.contains("adsf") && input.contains("qwer")) {
execute();
}
正如您所看到的,为多个单词执行此操作会变得很烦人。这是唯一的方法还是有更好的方法来检测多个子串?有没有办法检测订单?
答案 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