1. ๋ฌธ์ ์ค๋ช ๐
2. ๊ตฌํ ๋ฐฉ๋ฒ ๐๏ธ
KEY WORD
: ํธ๋ผ์ด
- 0๏ธโฃ
์ค์ํ ์ฒ์ ์ธํ !
: Tri ๊ตฌ์กฐ๋ฅผ ๋ง๋๋๋ฐ ๊ตฌ์ฑ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.(a) `๊ธฐ๋ณธ์ ์ธ ์์ ๋ ธ๋`: HashMap<Character, Node>๋ก ๊ตฌํ (์์ ์ํ๋ฒณ ์ด๋ฆ, ๊ทธ๊ฒ์ ๊ฐ์ฒด)
(b) `lenMap`: ํ์ฌ ์กฐํ ์ค์ธ ๋ฌธ์ ๋ค๋ก ๋ถํฐ ์ ๋ถ ๋ฌผ์ํ๋ผ๊ณ ์ณค์ ๋, ๊ทธ ์์ผ๋์นด๋๋ฅผ ๋ง์กฑํ๋ ๋ฌธ์๊ฐ ๋ช ๊ฐ ์๋์ง ์ธ๋ ์๋ฃ๊ตฌ์กฐ, HashMap<Integer, Integer>๋ก ๊ตฌํ (๋ฌธ์์ด์ ๊ธธ์ด, ๋ง์กฑํ๋ ๋ฌธ์ ๊ฐ์)
- 1๏ธโฃ
์ ๋ ฅ
: ๋ฌธ์์ด ๊ทธ๋๋ก ๋ฐ๋ Tri ํ๋, ๋ฌธ์์ด์ ๋ค์ง์ด์ ๋ฐ๋ Tri ํ๋์ฉ ๋ง๋ค์ด ๊ฐ๊ฐ ๋ฐ๋ก ๋ฐ๋ก ์ ๋ ฅ ๋ฐ์- ์ ๋ ฅ๋ฐ์ผ๋ฉด์, ๋งค๋ฒ LenMap์ ๊ฐ์ ๊ฐฑ์ ํ๋ค.
- 2๏ธโฃ
์ฐพ๊ธฐ
: ์์ผ๋์นด๋?
๋ฅผ ๋ง๋๊ธฐ ์ ๊น์ง, ํธ๋ผ์ด๋ฅผ ๊น๊ฒ ๋ค์ด๊ฐ๋ค. ๋ฐํ๊ฐ์ด ๋ ans์ ํ์ฌ ์กฐํ์ค์ธ ๋ฌธ์์ lenMap์์ ํ ๋ฌธ์์ด ๊ธธ์ด๋ฅผ ๊ฐ์ง๋ ๊ฐ์ ๊ฐ์๊ฐ ๋ช๊ฐ ์๋ ํญ์ ์ฐพ์์ ์๋ก ์ ์ฅ์ํจ๋ค.
์ด ๋ฌธ์ ๋ lenMap์ ๋ํด ์ดํด ๋ชปํ๋ฉด ํ ์์ด ์ด๋ ค์์ง๋ค. ์ง๊ธ๋ถํฐ ๊ตฌํ ๋ฐฉ๋ฒ์ ํ๋์ฉ ํด์ค ํ๊ฒ ๋ค.
(0) LenMap์ด๋
๊ธฐ๋ณธ ํธ๋ผ์ด๋ฅผ ๊ตฌํํ๋ฉด ์์ ๊ฐ๋ค. ์ฌ๊ธฐ์ LenMap์ ๋ถ์ฌ ๋ณด๊ฒ ๋ค. (+ ํด๋น ๋ ธ๋๊ฐ ๋จ์ด์ ๋์ธ์ง ํ์ธํ๋ boolean๊ฐ์ ํด๋น ๋ฌธ์ ์์ ํ์์์ด์ ์ญ์ ํจ)
๊ฐ ๋ ธ๋ ๋ณ lenMap์ ๋ํ๋ด์๋ค. ๊ฐ๊ฐ์ ์์๋ key=value ํํ๋ก ๋ํ๋ด์๋ค. ๋ฌด์จ ๋ป์ธ์ง ์๋ฅผ ๋ค์ด ์ดํดํด๋ณด์.
๋งจ ์ข์๋จ์ f
์ ๋ถ์ lenMap์ ์๋ฏธ๋ฅผ ๋ณผ๊น? ์ด๊ฒ์ f????
๋ฅผ ๋ง์กฑ์ํค๋ ๋จ์ด์ ๊ฐ์๊ฐ 4๊ฐ์ด๊ณ , f?????
๋ฅผ ๋ง์กฑ์ํค๋ ๋จ์ด๋ 1๊ฐ ์๋ค๋ ๊ฒ์ด๋ค. ์ค๊ฐ์ a
์ lenMap์ fra??
๋ฅผ ๋ง์กฑ์ํค๋ ๋จ์ด๊ฐ 1๊ฐ ์กด์ฌํ๋ค๋ ๊ฒ์ด๋ค.
๋งค ๋ฌธ์๋ฅผ ์กฐํํ ๋๋ง๋ค ๊ทธ ๋ฌธ์์ lenMap์ map.put(๋ฌธ์์ด์ ๊ธธ์ด, ํด๋น key์ ์ด์ value + 1)
์ ๊ณ์ฐ ํด์ฃผ๋ฉด, ์ด๊ฒ์ ์ดํ ์ฟผ๋ฆฌ ๊ณ์ฐ ๋, ํ ๋ฌธ์ ์ดํ๋ก ? ๋ง ์จ๋ค๊ณ ์ณค์ ๋, ๊ทธ ๋ฌผ์ํ์ ๊ธธ์ด ๋ณ๋ก ๋ง์กฑ์ํฌ ์ ์๋ ๋จ์ด์ ๊ฐ์๋ฅผ ์๋ฏธํ๊ฒ ๋๋ค.
root ๋ ธ๋์ LenMap์๋ ๊ผฌ๋ฐ๊ผฌ๋ฐ ๊ฐ์ ๊ณ์ฐํด์ฃผ๋ ์ด์ โจ
๋ด๊ฐ ํ์๊ฐ ๋ฐ์ ํค๋ฉ ๋ถ๋ถ์ด๋ค. ์ด๊ฒ์ ํด๊ฒฐํ์ง ์์ผ๋ฉด ํจ์จ์ฑ ํ
์คํธ 3๋ฒ์ ๊ณ์ ํต๊ณผ ๋ชปํ๋ค. ๋ฐ๋ก ๋ชจ๋ ๋ฌธ์๊ฐ ์์ผ๋ ์นด๋๋ก ์ด๋ฃจ์ด์ง ์ฟผ๋ฆฌ๋ฌธ์ ๋ํ ๊ณ์ฐ
์ ์ํด์ ์ด๋ค. Root์ lenMap์ ๋ฌธ์ ์์ด ๋ชจ๋ ๊ฒ ์์ผ๋ ์นด๋๋ก ์ด๋ฃจ์ด์ง ์ฟผ๋ฆฌ๋ฌธ์ ๋ํ ๊ณ์ฐ์ ์ํ ๊ฒ์ด๋ค.
(1) ๋ฌธ์์ด์ ๋ค์ง์ด์ ์ ์ฅํ๋ ํธ๋ผ์ด๊ฐ ํ์ํ ์ด์
ํด๋น ๋ฌธ์ ์์๋ ํ๋ฏธ๋ง ์์ผ๋ ์นด๋์ธ ๊ฒฝ์ฐ์ ๋๋ถ์ด ์ ๋๊ฐ ์์ผ๋ ์นด๋์ธ ๊ฒฝ์ฐ๋ ๊ตฌํ๋ผ๊ณ ํ๋ค.
๋ง์ฝ ๋ฆฌ๋ฒ์ค ํธ๋ผ์ด ์์ด ๊ฐ์ ๊ตฌํ๋ฉด ์ ๋์ฌ์ ์์ผ๋ ์นด๋ ์๋งํผ ํ DEPTH์ 26๊ฐ์ ์์์ ๋์๋ด์ผ ํ๋ค. ์ด๋ ๋จ์ด์ ๊ธธ์ด๊ฐ 10000๊ฐ ์ผ ์ ์์์ผ๋ก ์ต์
์ ๊ฒฝ์ฐ $26^{10000}$์ ๊ณ์ฐ์ ์ํํ๊ฒ ํ๋ฏ๋ก ํํ ์๊ฐ ์ด๊ณผ
๋ฅผ ์ผ์ผํจ๋ค.
๋ฐ๋ผ์ ๋ฌธ์์ด์ ๋ค์ง์ด ์ ์ฅํ๋ ๋ฆฌ๋ฒ์ค ํธ๋ผ์ด๊ฐ ํ์ํ๋ค. ๊ฐ๋ น ๋ฌธ์ ์ ์์ ์ฒ๋ผ "????o"
๋ฅผ ๊ตฌํ๋ค๊ณ ํด๋ณด์. ์
๋ ฅ์ ๋ฆฌ๋ฒ์ค ํธ๋ผ์ด๋ก ์ ์ฅํ ํํ๋ ๋ค์๊ณผ ๊ฐ๋ค.
์์ ๊ฐ์ด o
๊ฐ ์ ๋์ฌ๊ฐ ๋์ด ๋จ์ด ํ๋ฏธ๊ฐ ์์ผ๋์นด๋์ธ ๊ฒฝ์ฐ์ ๋๊ฐ์ด ๊ณ์ฐํด์ฃผ๋ฉด ๋๋ค. (๊ทธ๋ฆผ์ ๊ท์ฐฎ์์ ๋ค์ง์์ ๋, o๊ฐ ์์ผ๋ก ์ค๋ ๊ฒ๋ง ๊ทธ๋ ธ๋ค. ์ค์ ๋ก๋ ๋ ๋ง์ ๋
ธ๋๊ฐ ์๋ค.)
(2) ์ฐพ๊ธฐ
์ฐพ๊ธฐ๋ ์ง์ง ๋ฌผ์ํ๋ฅผ ๋ง๋๊ธฐ ์ ๊น์ง, ๋งค ๋ ธ๋์์ ํ ๋ ธ๋๊ฐ ๋ง์ง๋ง ๋จ์ด์ผ ๊ฒ์ด๋ผ ์๊ฐํ๊ณ ์ ๋ ฅ์ผ๋ก ๋ค์ด์จ str์ ๊ธธ์ด๋งํผ์ lenMap value๊ฐ ์ผ๋ง์ธ์ง ํ์ธํด์ฃผ๋ฉด ๋๋ค.
(1) ์๊ฐ๋ณต์ก๋ ๋ถ์ ๐
๋ง์ฝ ?๊ฐ ์์ ๊ฒฝ์ฐ, ์์ ์ํ๋ฒณ์ ๋ชจ๋ ํ์ธํ์ ๊ฒฝ์ฐ $O(26^{h})$์ ์๊ฐ์ด ๋ค๊ฒ์ด๋ค. (h
= ํธ๋ผ์ด์ ๋์ด)
ํ์ง๋ง ์์ ๊ฐ์ด ๊ตฌํ๋ฉด ์ ์ ํธ๋ผ์ด๋๋ก $O(NM)$์ ์๊ฐ์ด ๋ ๋ค. (N
= ์ฟผ๋ฆฌ์ ๊ฐ์, M
= ๋ฌธ์์ด์ ๊ธธ์ด)
3. ์ฝ๋ ์๊ฐ ๐
import java.io.*;
import java.util.*;
class Tri {
Node root;
public Tri() {
root = new Node();
}
public void insert(String str) {
Node now = this.root;
for(int i = 0; i < str.length(); i++){
char c = str.charAt(i);
now.children.putIfAbsent(c, new Node());
now.lenMap.compute(str.length(), (k,ov) -> ov == null? 1 : ov + 1);
now = now.children.get(c);
}
}
public int find(String str) {
int ans = 0;
Node now = this.root;
if(str.charAt(0) == '?') ans = now.lenMap.getOrDefault(str.length(), 0);
for(int i = 0; i < str.length(); i++){
char c = str.charAt(i);
if(c =='?') break;
if(!now.children.containsKey(c)) return 0; // ์ด๋ฐ ๋ฌธ์ ๊ฐ์ง๊ณ ์์ง ์์.
now = now.children.get(c);
ans = now.lenMap.getOrDefault(str.length(),0);
}
return ans;
}
}
class Node {
HashMap<Character, Node> children;
HashMap<Integer, Integer> lenMap;
public Node() {
children = new HashMap<>();
lenMap = new HashMap<>();
}
}
class Solution {
public int[] solution(String[] words, String[] queries) {
int[] answer = new int [queries.length];
Tri tri = new Tri();
Tri irt = new Tri();
for(int i = 0; i < words.length; i++){
tri.insert(words[i]);
irt.insert(reverse(words[i]));
}
for(int i = 0; i < queries.length; i++){
String now = queries[i];
if(now.charAt(0) != '?') {
answer[i] = tri.find(now);
}else{
answer[i] = irt.find(reverse(now));
}
}
return answer;
}
public String reverse (String str) {
return new StringBuilder(str).reverse().toString();
}
}
(1) insert ๋ถ๋ถ
public void insert(String str) {
Node now = this.root;
for(int i = 0; i < str.length(); i++){
char c = str.charAt(i);
now.children.putIfAbsent(c, new Node());
now.lenMap.compute(str.length(), (k,ov) -> ov == null? 1 : ov + 1);
now = now.children.get(c);
}
}
compute
ํจ์๋ฅผ ํ์ฉํด, null์ธ ๊ฒฝ์ฐ์ ๋ํ ๊ณ์ฐ๋ ๋ค๋ฅธ ์ฝ๋ ์์ด ํ๋ค.
(2) find ๋ถ๋ถ
public int find(String str) {
int ans = 0;
Node now = this.root;
if(str.charAt(0) == '?') ans = now.lenMap.getOrDefault(str.length(), 0);
for(int i = 0; i < str.length(); i++){
char c = str.charAt(i);
if(c =='?') break;
if(!now.children.containsKey(c)) return 0; // ์ด๋ฐ ๋ฌธ์ ๊ฐ์ง๊ณ ์์ง ์์.
now = now.children.get(c);
ans = now.lenMap.getOrDefault(str.length(),0);
}
return ans;
}
getOrDefault()
๋ก null Exception์ ํผํ๋ค.
4. ๋ฐฐ์ด ๊ฒ๋ค ๐ฏ
(1) ๋ฐ๋ชฉ์ ์ก๋ ํจ์จ์ฑ
๋งจ ์ฒ์ ์ฝ๋๋ ์์ผ๋ ์นด๋ ?
๋ง๋ ์ ๋ชจ๋ ์์ ์ํ๋ฒณ์ ๋ค์ ธ์ ํ์ธํ๋ ๊ฒ์ผ๋ก ํ๋ค. ์ ํ๋๋ ๋ค ๋งํ์ง๋ง, ํจ์จ์ฑ 1,2,3์ ๋ํํ์ง ๋ชปํ๋ค.
import java.io.*;
import java.util.*;
class Solution {
public int[] solution(String[] words, String[] queries) {
int[] answer = new int [queries.length];
Tri tri = new Tri();
for(int i = 0; i < words.length; i++){
tri.insert(words[i]);
}
for(int i = 0; i < queries.length; i++){
String now = queries[i];
if(now.charAt(0) != '?') {
answer[i] = tri.cntPrefix(now);
}else{
answer[i] = tri.cntSuffix(now);
}
}
return answer;
}
}
class Tri {
Node root;
public Tri() {
root = new Node();
}
public void insert(String str) {
Node now = this.root;
for(int i = 0; i < str.length(); i++){
char c = str.charAt(i);
now.children.putIfAbsent(c, new Node());
now = now.children.get(c);
}
now.isEnd = true;
}
public int cntPrefix(String query) {
int ans = 0;
Node now = this.root;
// ํ์์ ์ธ ๋ฌธ์ ๋ค ๋ค์ด๊ฐ๋์ง ํ์ธ
int i = 0;
for(; i < query.length(); i++){
char c = query.charAt(i);
if(c == '?') break;
if(!now.children.containsKey(c)) return 0; // ์ฟผ๋ฆฌ์ ๋ฌธ์๋ถ๋ถ์ ๋ง์กฑํ์ง ๋ชปํ๋ค๋ ๋ป
now = now.children.get(c);
}
ans += cntPrefix(query.length() - i, now);
return ans;
}
private int cntPrefix(int leftover, Node now){
if(leftover == 0 && now.isEnd) return 1;
int cnt = 0;
for(Character key : now.children.keySet()){
Node child = now.children.get(key);
cnt += cntPrefix(leftover-1, child);
}
return cnt;
}
public int cntSuffix(String str) {
Node now = this.root;
int wild_card_cnt = 0;
String left = "";
for(int i = 0; i < str.length(); i++){
if(str.charAt(i) == '?') wild_card_cnt++;
else left += str.charAt(i);
}
return cntSuffix(now, wild_card_cnt, left);
}
private int cntSuffix ( Node now, int leftover, String left) {
// ๊ธฐ์ ์กฐ๊ฑด
if(leftover == 0 && left.length() == 0 && now.isEnd) return 1;
if(leftover == 0 && left.length() != 0){
for(int i = 0; i < left.length(); i++){
Character c = left.charAt(i);
if(now.children.containsKey(c)) {
now = now.children.get(c);
}else {
return 0;
}
}
if(now.isEnd) return 1;
}
// ๊ณ์ฐ
int ans = 0;
for(Character key : now.children.keySet()) {
Node child = now.children.get(key);
ans += cntSuffix(child, leftover-1, left);
}
return ans;
}
}
class Node {
HashMap<Character, Node> children;
boolean isEnd;
public Node() {
children = new HashMap<>();
isEnd = false;
}
}
lenMap ์๋ฃ๊ตฌ์กฐ ํ์ฉ์ ๋ณด๋ฉฐ, ์์ผ๋ฅผ ๋ํ๋ค.