問題にチャレンジして、ユーザー同士で解答を教え合ったり、コードを公開してみよう!
1 つ前の問題「構造体によるトライ木の構築」では1つの文字列をトライ木に格納しました。
この問題では複数の文字列を格納できるトライ木を作成します。
トライ木の頂点を表す Node
クラスにメンバ変数 is_end: bool
を追加してください。
さらにトライ木全体を表すクラス Trie
を作成し、Node
はその内部クラスとしてください。Node
と Trie
はそれぞれ次のようなメンバ変数、メンバ関数を持つクラスとなります。
Nodeクラス //トライ木の各頂点を表すクラス
-----------------------------------
メンバ変数
child[ch]: Node (chをキーとして、頂点の情報を返す配列) //文字 ch をラベルとして持つ辺を通って進める頂点を表す
is_end: bool //この頂点は格納されたキーの最後の頂点であるか(trueならそう)
Trieクラス //トライ木全体を表すクラス
-----------------------------------
メンバ変数
root: Node //トライ木の根を表す
-----------------------------------
メンバ関数
insert(word: string): void //文字列 word をトライ木に格納する
Trie
のメンバ関数 insert(word: string): void
を実装してもらいます。word
をトライ木に格納する関数です。この関数では word
のプレフィックスに対応する頂点が存在しないときに新しく頂点を作成するという動作が求められます。これは C++, Python ではそれぞれ次のように実装することが出来ます。// 文字 ch で移動できる新しい頂点を作成する実装例
Node *ptr; // ptrは今いる頂点を表す
ptr->child[ch-'a'] = new Node();
# 文字 ch 移動できる新しい頂点を作成する実装例 ptrは今いる頂点を表す
ptr.child[ord(ch) - ord("a")] = Trie.Node()
Node
クラスに追加したメンバ変数 is_end
はトライ木に "aaa" と "aaaaaaa" のような、一方の文字列のプレフィックスがもう一方の文字列であるような 2 つの異なる文字列が格納されていた場合に "aaa" を識別するために必要になります。is_end
が true
である頂点はトライ木に格納された文字列の最後の文字に対応することを示します。つまり、根から is_end
が true
である頂点への経路の文字列がトライ木に格納された文字列となります。insert()
を用いて文字列 T をトライ木に格納する手順を説明します。 1. 最初は根である trie のメンバ変数 root (ここは T{:0} に対応します) で T{:1} に対応する頂点が存在するかを確認する.
もし、そのような頂点が存在しなければ新しく作成し,trie のメンバ変数 child[] の適切な位置に辺を追加する.
2. T{:1} に対応する頂点へと移動する.
3. 手順 1, 2 と同じように, 今いる頂点が T{:i} (0≦i<|T|) に対応するなら T{:i+1} に対応する頂点 (なければ新しく作成する) に
進む, という処理を T{:|T|} に到達するまで行う.
4. T{:|T|} に対応する頂点のメンバ変数 is_end を true とする.
#
を出力してください・
N Q
S_1
...
S_N
query_1
...
query_Q
X Yの形式で与えられます。
i 行目では i 番目のクエリに対する出力を行ってください。
各クエリに対する出力結果は 1 行で、空白無し、文字が辞書順に並んでいるという条件を満たして出力してください。
また、末尾に改行を入れ、余計な文字、空行を含んではいけません。
すべてのテストケースにおいて、以下の条件をみたします。
・1 ≦ N ≦ 100
・S_i はアルファベット小文字で構成される
・1 ≦ |S_i| ≦ 10^3
・1 ≦ Q ≦ 10^4
・1 ≦ X ≦ N
・0 ≦ Y ≦ |S_X|
2 5
aa
ab
1 0
1 1
1 2
2 1
2 2
a
ab
#
ab
#
4 4
aaaa
aaba
aacb
abaa
1 1
2 2
3 3
4 4
ab
abc
b
#