2017-10-24 14 views
-1

今私は、このアルゴリズムに関する以前の質問があることを知っていますが、正直なところ、単純なJavaの実装に遭遇していません。多くの人がGitHubのプロファイルに同じコードをコピーして貼り付けています。Aho-Corasick文字列照合アルゴリズムのJava実装?

インタビューの目的で、別のアプローチを使ってアルゴリズムを設定して実装する予定です。

アルゴリズムは非常に困難な傾向があります。私は正直言って、それについてどうやって行くのか分からない。論理は意味をなさない。私は4日間近く、アプローチをスケッチしていたが、役に立たなかった。

あなたの知恵で教えてください。

私は主に1がここで自分のソリューションを実装することができればそれはビッグボーナスになり、この情報Intuition behind the Aho-Corasick string matching algorithm

に基づくアルゴリズムをやっています。場合は、コードでoverwhelemed、主な問題はアホ - Corasickの主なアルゴリズムであるあなたの

しかし、ここでは、私は本当にに引っかかって、次の不完全と動作していないソリューションです。すでに辞書のトライツリーを作成しています。

しかし、私たちはトライストラクチャーを持っているので、実際にどのように実装を開始するのかという問題です。

いずれも参考にしていませんでした。

public class DeterminingDNAHealth { 
 
    private Trie tree; 
 
    private String[] dictionary; 
 
    private Node FailedNode; 
 

 

 
    private DeterminingDNAHealth() { 
 

 
    } 
 

 
    private void buildMatchingMachine(String[] dictionary) { 
 
    this.tree = new Trie(); 
 
    this.dictionary = dictionary; 
 

 
    Arrays.stream(dictionary).forEach(tree::insert); 
 

 
    } 
 

 
    private void searchWords(String word, String[] dictionary) { 
 

 
    buildMatchingMachine(dictionary); 
 

 
    HashMap < Character, Node > children = tree.parent.getChildren(); 
 

 
    String matchedString = ""; 
 

 
    for (int i = 0; i < 3; i++) { 
 
     char C = word.charAt(i); 
 

 
     matchedString += C; 
 

 
     matchedChar(C, matchedString); 
 

 
    } 
 

 
    } 
 

 
    private void matchedChar(char C, String matchedString) { 
 

 

 
    if (tree.parent.getChildren().containsKey(C) && dictionaryContains(matchedString)) { 
 

 
     tree.parent = tree.parent.getChildren().get(C); 
 

 
    } else { 
 

 
     char suffix = matchedString.charAt(matchedString.length() - 2); 
 

 
     if (!tree.parent.getParent().getChildren().containsKey(suffix)) { 
 
     tree.parent = tree.parent.getParent(); 
 

 
     } 
 

 

 
    } 
 
    } 
 

 
    private boolean dictionaryContains(String word) { 
 

 
    return Arrays.asList(dictionary).contains(word); 
 

 
    } 
 

 

 
    public static void main(String[] args) { 
 

 
    DeterminingDNAHealth DNA = new DeterminingDNAHealth(); 
 

 
    DNA.searchWords("abccab", new String[] { 
 
     "a", 
 
     "ab", 
 
     "bc", 
 
     "bca", 
 
     "c", 
 
     "caa" 
 
    }); 
 

 

 
    } 
 
}

私はセットアップに正常に動作トライデータ構造を有しています。だからここ

問題なしtrie.java

public class Trie { 
 
    public Node parent; 
 
    public Node fall; 
 

 
    public Trie() { 
 
    parent = new Node('⍜'); 
 
    parent.setParent(new Node()); 
 
    } 
 

 
    public void insert(String word) {...} 
 

 
    private boolean delete(String word) {...} 
 

 
    public boolean search(String word) {...} 
 

 
    public Node searchNode(String word) {...} 
 

 
    public void printLevelOrderDFS(Node root) {...} 
 

 
    public static void printLevel(Node node, int level) {...} 
 

 
    public static int maxHeight(Node root) {...} 
 

 
    public void printTrie() {...} 
 

 
}

ノードの同じこと。

Node.java

public class Node { 
 

 
    private char character; 
 
    private Node parent; 
 
    private HashMap<Character, Node> children = new HashMap<Character, Node>(); 
 
    private boolean leaf; 
 

 
    // default case 
 
    public Node() {} 
 

 
    // constructor accepting the character 
 
    public Node(char character) { 
 
    this.character = character; 
 
    } 
 

 
    public void setCharacter(char character) {...} 
 

 
    public char getCharacter() {...} 
 

 
    public void setParent(Node parent) {...} 
 

 
    public Node getParent() {...} 
 

 
    public HashMap<Character, Node> getChildren() {...} 
 

 
    public void setChildren(HashMap<Character, Node> children) {...} 
 

 
    public void resetChildren() {...} 
 

 
    public boolean isLeaf() {...} 
 

 
    public void setLeaf(boolean leaf) {...} 
 
}

+0

* "正直なところ、**単純な** Java実装" * --- * "アルゴリズムは非常に難しい**傾向があります。" * ---おそらくそれが理由です。 – Andreas

+0

したがって、私は大多数が理解できるように、より簡単なアプローチを実装するためにあなたの助けを欲しがっていますよね? @Andreas – OOP

+0

*「論理は意味をなさない」* ---アルゴリズムを理解できない場合は、コード化する方法がありません。 – Andreas

答えて

1

私は通常、高度なデータ構造を1年おきに教えます。文字列データ構造を調べるときは、Aho-Corasickオートマトンを扱います。いくつかのより遅いものを最適化することによってアルゴリズムを開発する方法を示すスライドが利用可能であるhereがあります。

は、一般的に言って、私がダウンして4つのステップへの実装を破るだろう:

  1. はトライをビルドします。そのコアでは、Aho-Corasickのオートマトンはいくつかの矢印を追加したトライです。このアルゴリズムの最初のステップは、このトライを作成することです。これは通常のトライの構築と同じように進んでいます。実際には、このステップを実装することをお勧めします。ちょうどトライを作成していて、後のステップを予期することは何もしていないようです。

  2. サフィックス(失敗)リンクを追加します。このアルゴリズムのこのステップでは、重要な障害リンクが追加されます。このリンクは、トライエッジに従うことができない文字に遭遇するたびに使用されます。これらの作業がリンクされた講義スライドにどのようにあるのかについて私が持っている最良の説明です。アルゴリズムのこのステップは、トライ上の幅優先探索ウォークとして実装されます。これをコーディングする前に、一般的なパターンを得るために手作業でいくつかの例を試してみることをお勧めします。いったんこれを行うと、コード化するのは特に難しいことではありません。しかし、どのように動作するのか完全に理解せずにこれをコーディングしようとすると、デバッグを悪夢にさせるでしょう!

  3. 出力リンクを追加します。このステップでは、トライの所定のノードで一致するすべての文字列を報告するために使用されるリンクを追加します。これは、トライの第2の幅優先探索によって実現されています。また、それがどのように機能するかについての最良の説明はスライドにあります。良いことは、BFSのやり方や、トライをどのように歩くかをよりよく理解しているため、この手順はサフィックスリンクの構築よりも実際に実装する方がはるかに簡単だということです。あなたが快適にこれを手で行うことができない限り、これをコード化しようとしないでください!最小限のコードは必要ありませんが、高レベルの動作を理解できないデバッグコードが残っていても構いません。

  4. マッチャを実装します。このステップはあまりにも悪くありません!あなたは単に入力から文字を読むトライを歩いて、各ステップですべてのマッチを出力し、つまずくときはいつでも失敗リンクを使用し、下に進むことはできません。

これは、モジュール化されたタスクの内訳と、プロセス全体がどのように動作するかについての参考情報を提供したいと考えています。がんばろう!

+0

ありがとう!スライドを転送することを本当に感謝します。すごい!私はあなたが実装をいくつかの段階に細分化したのが好きです。私はトライツリーを構築することを意味init自己は非常に簡単です。トリッキーな部分は失敗リンクとマッチャーです。私はあなたのスライドを勉強しています。再度、感謝します :) – OOP

5

あなたは、いくつかのソースコードを読むことによって​​の十分な理解を得るためにつもりはありません。アルゴリズムが簡単ではないので、簡単な実装を見つけることはできません。

オリジナルペーパーEfficient String Matching: An Aid to Bibliographic Searchはよく書かれており、非常に親切です。私はあなたがそのPDFをダウンロードし、それを注意深く読んで、少し考えて、もう一度それを読むことをお勧めします。 研究紙。

他のアルゴリズムの説明を読むと便利かもしれません。テキストの説明、図、Powerpointスライドなど、多くのページがあります。

これを実装する前に、少なくとも1日か2日はそれらのリソースを調べることをお勧めします。どのように動作しているかを完全に理解することなく実装しようとすると、あなたは失われてしまい、実装ではそれが表示されるためです。アルゴリズムはまったく単純ではありませんが、かなり親しみやすいものです。

コードがほしいのであれば、ここには良い実装があります:https://codereview.stackexchange.com/questions/115624/aho-corasick-for-multiple-exact-string-matching-in-java

+0

私は、 "効率的な文字列マッチング:書誌検索への援助"というリンクが紙を直接指すことを期待しました。このようなリンクがあれば、それを含めることは素晴らしいことです。 – erickson

+0

@erickson:リンクを修正しました。メモをありがとう。 –

+0

@ JimMischelありがとうございました。本当にリンクを転送していただきありがとうございます。私はすぐにスキンを通過し、その素晴らしい。私は勉強してうまくいけばアルゴリズムを手に入れるつもりです。 :) – OOP