プレフィックスツリーを実装する
Trie (「トライ」と発音) またはプレフィックス ツリーは、
文字列のデータセットからキーを効率的に格納および取得するために使用されるツリー状のデータ構造です。このデータ構造には、オートコンプリートやスペル チェックなど、非常に多くの用途があります。
リートコード 208 https://leetcode-cn.com/problems/implement-trie-prefix-tree/
多くの検索エンジンはこの方法で実装しています
一般に、ルート ノードには値が格納されず、他の各ノードには 1 つの文字が格納されます。
ここでは HashMap 実装を使用します。これは、この実装方法のほうがノードを追加するのがより柔軟であるためです。
class TrieNode {
public Character vaCharacter;
public Map<Character, TrieNode> children = new HashMap<>();
private boolean isEnd;
public TrieNode(char val) {
vaCharacter = val;
}
public TrieNode() {
}
public boolean existStr(){
return isEnd;
}
public void setTrue(){
isEnd = true;
}
public TrieNode getChildStr(char val) {
if(children.containsKey(val)) {
return children.get(val);
}
return null;
}
};
パラメータの説明:
1. 子: すべての子ノードで構成される val-val オブジェクトのマップ。文字列を見つける
のがより便利で
、プレフィックスと文字列を区別しやすい)
- 追加操作
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode exangeNode = root;
for(int i = 0; i < word.length(); i++){
TrieNode temp = exangeNode.getChildStr(word.charAt(i));
if(temp == null){
exangeNode.children.put(word.charAt(i),new TrieNode());
}else{
}
exangeNode = exangeNode.getChildStr(word.charAt(i));
}
exangeNode.setTrue();
}
- 文字列操作のチェック(クエリ文字列がプレフィックスツリーに存在するかどうか)
public boolean search(String word) {
TrieNode exangeNode = root;
for(int i = 0; i < word.length(); i++){
TrieNode temp = exangeNode.getChildStr(word.charAt(i));
if(temp == null){
return false;
}else{
exangeNode = exangeNode.getChildStr(word.charAt(i));
}
}
return exangeNode.existStr();
}
- プレフィックスの動作を確認する (プレフィックスが存在するかどうかを問い合わせる)
public boolean startsWith(String prefix) {
TrieNode exangeNode = root;
for(int i = 0; i < prefix.length(); i++){
TrieNode temp = exangeNode.getChildStr(prefix.charAt(i));
if(temp == null){
return false;
}else{
exangeNode = exangeNode.getChildStr(prefix.charAt(i));
}
}
return true;
}
全体的な実装コード:
class Trie {
TrieNode root;
/** Initialize your data structure here. */
public Trie() {
root = new TrieNode();
}
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode exangeNode = root;
for(int i = 0; i < word.length(); i++){
TrieNode temp = exangeNode.getChildStr(word.charAt(i));
if(temp == null){
exangeNode.children.put(word.charAt(i),new TrieNode());
}else{
}
exangeNode = exangeNode.getChildStr(word.charAt(i));
}
exangeNode.setTrue();
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
TrieNode exangeNode = root;
for(int i = 0; i < word.length(); i++){
TrieNode temp = exangeNode.getChildStr(word.charAt(i));
if(temp == null){
return false;
}else{
exangeNode = exangeNode.getChildStr(word.charAt(i));
}
}
return exangeNode.existStr();
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TrieNode exangeNode = root;
for(int i = 0; i < prefix.length(); i++){
TrieNode temp = exangeNode.getChildStr(prefix.charAt(i));
if(temp == null){
return false;
}else{
exangeNode = exangeNode.getChildStr(prefix.charAt(i));
}
}
return true;
}
}
class TrieNode {
public Character vaCharacter;
public Map<Character, TrieNode> children = new HashMap<>();
private boolean isEnd;
public TrieNode(char val) {
vaCharacter = val;
}
public TrieNode() {
}
public boolean existStr(){
return isEnd;
}
public void setTrue(){
isEnd = true;
}
public TrieNode getChildStr(char val) {
if(children.containsKey(val)) {
return children.get(val);
}
return null;
}
};