Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检查干草堆是否包含针组的最快方法_Java_String_Algorithm_Pattern Matching - Fatal编程技术网

Java 检查干草堆是否包含针组的最快方法

Java 检查干草堆是否包含针组的最快方法,java,string,algorithm,pattern-matching,Java,String,Algorithm,Pattern Matching,我有一根草垛绳,我想检查它是否包含任何针绳。目前我是这样做的: Set<String> needles = ...; ... String [] pieces = haystack.split(" "); for (String piece: pieces) { if (needles.contains(piece) { return true; } } return false; 如果它真的是关于速度的,并且您希望搜索一个项目列表而不是一个固定的字符串,那么

我有一根草垛绳,我想检查它是否包含任何针绳。目前我是这样做的:

Set<String> needles = ...;

...

String [] pieces = haystack.split(" ");
for (String piece: pieces) {
  if (needles.contains(piece) {
    return true;
  }
}

return false;

如果它真的是关于速度的,并且您希望搜索一个项目列表而不是一个固定的字符串,那么您可以将工作划分为不同的线程(我不确定要检查多少个项目,但是如果不需要几分钟,这可能不是一种方法)


如果不需要将haystack生成一个数组,可以通过指针进行迭代,并通过String.contains()测试haystack

如果这一切都是关于速度的,并且您希望搜索一个项目列表而不是一个固定的字符串,那么您可以将工作划分为不同的线程(我不确定要检查多少个项目,但是如果不需要几分钟,这可能不是一种方法)


如果不需要将haystack生成一个数组,可以通过指针进行迭代,并通过String.contains()测试haystack

通常情况下,大多数减速都是split命令。搜索一个字符串比分配一大堆对象要好得多。您最好使用正则表达式,避免新的对象构造。使用Aho会非常有效。假设你的列表足够大而麻烦

public class NeedleFinder {
    static final int RANGEPERMITTED = 26;
    NeedleFinder next[];

    public NeedleFinder() {
    }
    public NeedleFinder(String haystack) {
        buildHaystack(haystack);
    }

    public void buildHaystack(String haystack) {
        buildHaystack(this,haystack,0);
    }

    public void buildHaystack(NeedleFinder node, String haystack, int pos) {
        if (pos >= haystack.length()) return;
        char digit = (char) (haystack.charAt(pos) % RANGEPERMITTED);
        if (digit == ' ') {
            buildHaystack(this,haystack,pos+1);
            return;
        }
        if (node.next == null) node.next = new NeedleFinder[RANGEPERMITTED];
        if (node.next[digit] == null) node.next[digit] = new NeedleFinder();
        NeedleFinder nodeNext = node.next[digit];
        buildHaystack(nodeNext,haystack,pos+1);
    }
    public boolean findNeedle(String needle) {
        return findNeedle(this, needle,0);
    }
    private boolean findNeedle(NeedleFinder node, String needle, int pos) {
        if (pos >= needle.length()) return true;
        char digit = (char) (needle.charAt(pos) % RANGEPERMITTED);
        if (node.next == null) return false;
        if (node.next[digit] == null) return false;
        return findNeedle(node.next[digit],needle,pos+1);
    }
}
如果成功,请检查包含的内容,以确保它不是假阳性。但是,它很快。我们说的是二进制搜索速度的五分之一

说到搜索,二进制搜索是个好主意。这是在正确的时间复杂性单独。只需对你愚蠢的草堆字符串列表进行排序,然后当你查看指针时进行二进制搜索。在java中,这些是集合中的基本项。.sort()和.binarySearch()命令。这将是一个数量级的好比野蛮

value = Collections.binarySearch(haystackList, needle, strcomp);
如果该值为正值,则已找到该值

Collections.sort(words, strcomp);
用strcomp

public Comparator<String> strcomp = new Comparator<String>() {
    @Override
    public int compare(String s, String t1) {
        if ((s == null) && (t1 == null)) return 0;
        if (s == null) return 1;
        if (t1 == null) return -1;
        return s.compareTo(t1);
    }
};
公共比较器strcomp=新比较器(){
@凌驾
公共整数比较(字符串s、字符串t1){
if((s==null)和&(t1==null))返回0;
如果(s==null)返回1;
if(t1==null)返回-1;
返回s.compareTo(t1);
}
};

一般来说,大多数减速都是split命令。搜索一个字符串比分配一大堆对象要好得多。您最好使用正则表达式,避免新的对象构造。使用Aho会非常有效。假设你的列表足够大而麻烦

public class NeedleFinder {
    static final int RANGEPERMITTED = 26;
    NeedleFinder next[];

    public NeedleFinder() {
    }
    public NeedleFinder(String haystack) {
        buildHaystack(haystack);
    }

    public void buildHaystack(String haystack) {
        buildHaystack(this,haystack,0);
    }

    public void buildHaystack(NeedleFinder node, String haystack, int pos) {
        if (pos >= haystack.length()) return;
        char digit = (char) (haystack.charAt(pos) % RANGEPERMITTED);
        if (digit == ' ') {
            buildHaystack(this,haystack,pos+1);
            return;
        }
        if (node.next == null) node.next = new NeedleFinder[RANGEPERMITTED];
        if (node.next[digit] == null) node.next[digit] = new NeedleFinder();
        NeedleFinder nodeNext = node.next[digit];
        buildHaystack(nodeNext,haystack,pos+1);
    }
    public boolean findNeedle(String needle) {
        return findNeedle(this, needle,0);
    }
    private boolean findNeedle(NeedleFinder node, String needle, int pos) {
        if (pos >= needle.length()) return true;
        char digit = (char) (needle.charAt(pos) % RANGEPERMITTED);
        if (node.next == null) return false;
        if (node.next[digit] == null) return false;
        return findNeedle(node.next[digit],needle,pos+1);
    }
}
如果成功,请检查包含的内容,以确保它不是假阳性。但是,它很快。我们说的是二进制搜索速度的五分之一

说到搜索,二进制搜索是个好主意。这是在正确的时间复杂性单独。只需对你愚蠢的草堆字符串列表进行排序,然后当你查看指针时进行二进制搜索。在java中,这些是集合中的基本项。.sort()和.binarySearch()命令。这将是一个数量级的好比野蛮

value = Collections.binarySearch(haystackList, needle, strcomp);
如果该值为正值,则已找到该值

Collections.sort(words, strcomp);
用strcomp

public Comparator<String> strcomp = new Comparator<String>() {
    @Override
    public int compare(String s, String t1) {
        if ((s == null) && (t1 == null)) return 0;
        if (s == null) return 1;
        if (t1 == null) return -1;
        return s.compareTo(t1);
    }
};
公共比较器strcomp=新比较器(){
@凌驾
公共整数比较(字符串s、字符串t1){
if((s==null)和&(t1==null))返回0;
如果(s==null)返回1;
if(t1==null)返回-1;
返回s.compareTo(t1);
}
};
您应该看看算法。这适合您的问题,因为它构建了一个包含所有单词(针)的自动机,并在构建的自动机上遍历文本(草堆)以查找所有匹配的单词。它基本上构造了一个类似于trie的有限状态机

时间复杂度为
O(n+m+z)
z
是文本中出现的单词总数,
n
是文本长度,
m
是所有单词中的字符总数

编辑2

这是一个直接的实现,在找到任何针的第一次出现后停止遍历

import java.util.*;

class AhoCorasick {

  static final int ALPHABET_SIZE = 256;

  Node[] nodes;
  int nodeCount;

  public static class Node {
    int parent;
    char charFromParent;
    int suffLink = -1;
    int[] children = new int[ALPHABET_SIZE];
    int[] transitions = new int[ALPHABET_SIZE];
    boolean leaf;

    {
      Arrays.fill(children, -1);
      Arrays.fill(transitions, -1);
    }
  }

  public AhoCorasick(int maxNodes) {
    nodes = new Node[maxNodes];
    // create root
    nodes[0] = new Node();
    nodes[0].suffLink = 0;
    nodes[0].parent = -1;
    nodeCount = 1;
  }

  public void addString(String s) {
    int cur = 0;
    for (char ch : s.toCharArray()) {
      int c = ch;
      if (nodes[cur].children[c] == -1) {
        nodes[nodeCount] = new Node();
        nodes[nodeCount].parent = cur;
        nodes[nodeCount].charFromParent = ch;
        nodes[cur].children[c] = nodeCount++;
      }
      cur = nodes[cur].children[c];
    }
    nodes[cur].leaf = true;
  }

  public int suffLink(int nodeIndex) {
    Node node = nodes[nodeIndex];
    if (node.suffLink == -1)
      node.suffLink = node.parent == 0 ? 0 : transition(suffLink(node.parent), node.charFromParent);
    return node.suffLink;
  }

  public int transition(int nodeIndex, char ch) {
    int c = ch;
    Node node = nodes[nodeIndex];
    if (node.transitions[c] == -1)
      node.transitions[c] = node.children[c] != -1 ? node.children[c] : (nodeIndex == 0 ? 0 : transition(suffLink(nodeIndex), ch));
    return node.transitions[c];
  }

  // Usage example
  public static void main(String[] args) {
    AhoCorasick ahoCorasick = new AhoCorasick(1000);
    ahoCorasick.addString("big");
    ahoCorasick.addString("tasty");

    String s = "I am a big tasty potato";
    int node = 0;
    for (int i = 0; i < s.length(); i++) {
      node = ahoCorasick.transition(node, s.charAt(i));
      if (ahoCorasick.nodes[node].leaf) {
        System.out.println("A match found! Needle ends at: " + i); // A match found! Needle ends at: 9
        break;
      }
    }
  }
}
import java.util.*;
职业病{
静态最终整数字母表大小=256;
节点[]节点;
int nodeCount;
公共静态类节点{
int父代;
来自父代的字符;
int suffLink=-1;
int[]children=新int[字母表大小];
int[]转换=新int[字母表大小];
布尔叶;
{
数组。填充(子级,-1);
数组。填充(转换,-1);
}
}
公共节点(int-maxNodes){
节点=新节点[maxNodes];
//创建根
节点[0]=新节点();
节点[0]。suffLink=0;
节点[0]。父节点=-1;
nodeCount=1;
}
公共void addString(字符串s){
int cur=0;
for(char ch:s.toCharArray()){
int c=ch;
if(节点[cur].子节点[c]=-1){
节点[nodeCount]=新节点();
节点[nodeCount]。父节点=cur;
节点[nodeCount].charFromParent=ch;
节点[cur].子节点[c]=nodeCount++;
}
cur=节点[cur]。子节点[c];
}
节点[cur].leaf=true;
}
公共内部链接(内部节点索引){
节点=节点[nodeIndex];
如果(node.suffLink==-1)
node.suffLink=node.parent==0?0:转换(suffLink(node.parent)、node.charFromParent);
返回node.suffLink;
}
公共int转换(int nodeIndex,char ch){
int c=ch;
节点=节点[nodeIndex];
if(节点转换[c]=-1)
node.transitions[c]=node.children[c]!=-1?node.children[c]:(nodeIndex==0?0:transition(suffLink(nodeIndex),ch));
返回node.transitions[c];
}
//用法示例
公共静态void main(字符串[]args){
ahocarasick ahocarasick=新ahocarasick(1000);
ahocarasick.addString(“大”);
ahocarasick.addString(“美味”);
String s=“我是一个美味的大土豆”;
int节点=0;
对于(int i=0;i