๊ด€๋ฆฌ ๋ฉ”๋‰ด

be_better

[์ž๋ฃŒ๊ตฌ์กฐ] ํŠธ๋ผ์ด (Trie) ๋ณธ๋ฌธ

์ž๋ฃŒ๊ตฌ์กฐ

[์ž๋ฃŒ๊ตฌ์กฐ] ํŠธ๋ผ์ด (Trie)

NiceTry 2023. 8. 24. 18:26

๋ชฉ์ฐจ

    ๐Ÿ“š ํŠธ๋ผ์ด (Trie)

    ๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๊ณ  ๋น ๋ฅด๊ฒŒ ํƒ์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ ํŠธ๋ฆฌ ํ˜•ํƒœ์˜ ์ž๋ฃŒ๊ตฌ์กฐ

    ๋ž˜๋”•์Šค ํŠธ๋ฆฌ(Radix tree), ์ ‘๋‘์‚ฌ ํŠธ๋ฆฌ(Prefix tree), ํƒ์ƒ‰ ํŠธ๋ฆฌ(Retrieval tree) ๋“ฑ์œผ๋กœ ๋ถˆ๋ฆฌ๋ฉฐ

    Trie๋Š” Retrieval tree์—์„œ ํŒŒ์ƒ๋œ ๋‹จ์–ด๋‹ค.

     

    ๊ธฐ๋ณธ ๊ตฌ์กฐ

    ๋ฌธ์ž์—ด ์ง‘ํ•ฉ {"apple", "app", "agree", "eight", "elephant", "zero"} ์„ ํŠธ๋ผ์ด๋กœ ์ง์ ‘ ๊ตฌํ˜„

    ์žฅ์ 

    ๋ฌธ์ž์—ด์„ ๋น ๋ฅด๊ฒŒ ํƒ์ƒ‰ ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ๋‹จ์ 

    ํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํฌ๋‹ค๋Š” ๋‹จ์ 

    ์ด ๋ฉ”๋ชจ๋ฆฌ๋Š” O(ํฌ์ธํ„ฐ์˜ ํฌ๊ธฐ * ํฌ์ธํ„ฐ ๋ฐฐ์—ด์˜ ๊ฐœ์ˆ˜ * ์ด ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜) ๋งŒํผ ํ•„์š”

     

    ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด map ์ด๋‚˜ vector ์„ ์‚ฌ์šฉํ•ด ํ•„์š”ํ•œ ๋…ธ๋“œ๋งŒ ๋ฉ”๋ชจ๋ฆฌ์— ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹ ์ฑ„ํƒ


    ๐Ÿฆ‹ ํŠธ๋ผ์ด์˜ ์‚ฌ์šฉ์‚ฌ๋ก€

    • ์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ
    • ์‚ฌ์ „ ๊ฒ€์ƒ‰

    โœ๐Ÿป ํŠธ๋ผ์ด ADT (์ถ”์ƒ ๋ฐ์ดํ„ฐ ํƒ€์ž…)

    create() ํŠธ๋ผ์ด ์ƒ์„ฑ
    insert(str) ๋ฌธ์ž์—ด ์‚ฝ์ž…
    delete(str) ๋ฌธ์ž์—ด ์‚ญ์ œ
    search(str) ๋ฌธ์ž์—ด ํƒ์ƒ‰

     


    โš™๏ธ ํŠธ๋ผ์ด ๊ธฐ๋Šฅ & ๋™์ž‘์›๋ฆฌ

    ํŠธ๋ผ์ด ๋…ธ๋“œ ์ƒ์„ฑ

    • ๋ฌธ์ž์—ด์„ ์ด๋ฃจ๋Š” ์•ŒํŒŒ๋ฒณ, ๋‹ค์Œ ๋…ธ๋“œ ์Œ์˜ Map ๊ณผ
    • ํ˜„์žฌ ๋…ธ๋“œ๊ฐ€ ๋ฌธ์ž์—ด์˜ ๋ ๋…ธ๋“œ์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ boolean ํƒ€์ž…์˜ isTerminal๋ฅผ ๋ฉค๋ฒ„๋กœ ๊ฐ–๋Š” ํด๋ž˜์Šค ์ƒ์„ฑ
    class Node {
        HashMap<Character, Node> child;
        boolean isTerminal;
        
        public Node() {
        	this.child = new HashMap<>();
            this.isTerminal = false;
        }
    }

     

    ๋ฌธ์ž์—ด ์‚ฝ์ž…

    • ์•„๋ฌด๊ฒƒ๋„ ๋“ค์–ด์žˆ์ง€ ์•Š์€ root๋ถ€ํ„ฐ ์‹œ์ž‘
    • ๋ฌธ์ž์—ด์„ ์•ž์—์„œ๋ถ€ํ„ฐ ์ชผ๊ฐœ๋ฉด์„œ ๋ฌธ์ž๋ฅผ ํ•˜๋‚˜์”ฉ ํ™•์ธ
    • ์ด๋ฏธ ์žˆ๋Š” ๋ฌธ์ž๋ผ๋ฉด ๋‹ค์Œ ๋…ธ๋“œ๋กœ ์ด๋™
    • ์ด๋ฏธ ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ƒˆ๋กœ์šด ๋…ธ๋“œ ์ถ”๊ฐ€
    • ๋ฌธ์ž์—ด ๋ ๋ฌธ์ž๊นŒ์ง€ ๋„ฃ์—ˆ๋‹ค๋ฉด ๊ทธ ๋…ธ๋“œ์˜ isTerminal = true๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ  return
    // ์Šˆ๋„ ์ฝ”๋“œ
    
    Node root;
    public Trie() {
    	this.root = new Node();
    }
    
    public void insert(String str) {
    	Node cur = this.root;
        
        for (i = 0; str ๋๊นŒ์ง€) {
        	Character c = str.charAt(i);
            
            if (์ด๋ฏธ ์žˆ๋Š” ๋ฌธ์ž๊ฐ€ ์•„๋‹ˆ๋ฉด) {
            	cur.child.put(c, new Node()); // ์ƒˆ๋กœ์šด ๋…ธ๋“œ ์ƒ์„ฑ
            } else (์ด๋ฏธ ์žˆ๋Š” ๋ฌธ์ž๋ผ๋ฉด) {
            	cur = cur.child.get(c); // ๋‹ค์Œ ๋…ธ๋“œ๋กœ ์ด๋™
            }
            
            if (str ๋๊นŒ์ง€ ๋‹ค ๋„ฃ์—ˆ๋‹ค๋ฉด) {
        		isTerminal = true;
                return;
            }
        }
    }

     

    ๋ฌธ์ž์—ด ์‚ญ์ œ

    • ๋ฌธ์ž๋ฅผ ํ•˜๋‚˜์”ฉ ๋น„๊ต
    • ์ฐพ์œผ๋ ค๋Š” ๋ฌธ์ž๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ ํ›„ ์—†์œผ๋ฉด false ๋ฆฌํ„ด
    • ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด index์ฆ๊ฐ€
    • ์ฆ๊ฐ€ํ•œ index์— ๋Œ€ํ•ด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด์™€ ๊ฐ™์•„์กŒ์ง€๋งŒ isTerminal์ด true๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด false ๋ฆฌํ„ด
    • true๋ผ๋ฉด ์ฐพ์œผ๋ ค๋Š” ๋ฌธ์ž์—ด์ด๊ธฐ ๋•Œ๋ฌธ์— ์‚ญ์ œ๋ฅผ ์œ„ํ•ด isTerminal์„ false๋กœ ๋จผ์ € ๋ฐ”๊ฟ”์คŒ
    • ๋‹ค์Œ ๋…ธ๋“œ๊ฐ€ ์—†๋‹ค๋ฉด ํ˜„์žฌ ๋…ธ๋“œ ์‚ญ์ œ
    • ๋ฌธ์ž์—ด์˜ ๊ธธ์ด์™€ ์•„์ง ๊ฐ™์ง€ ์•Š์€ ๋…ธ๋“œ์— ๋Œ€ํ•ด์„œ๋Š” ์žฌ๊ท€ํ•จ์ˆ˜ ์ด์šฉ
    • ์žฌ๊ท€ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๊ฐ€ false๋ผ๋ฉด false ๋ฆฌํ„ด
    // ์Šˆ๋„ ์ฝ”๋“œ
    
    public boolean delete(Node node, String str, int index) {
    	Character c = str.charAt(index);
        
        if (๋ฌธ์ž๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š๋Š”๋‹ค๋ฉด) {
        	return false;
        }
        
        Node cur = node.child.get(c); // ๋‹ค์Œ ๋…ธ๋“œ ์ €์žฅ
        index ํ•˜๋‚˜ ์ฆ๊ฐ€;
        
        if (index๊ฐ€ ๋ฌธ์ž์—ด์˜ ๊ธธ์ด์™€ ๊ฐ™๋‹ค๋ฉด) {
        	if (isTerminal์ด false๋ผ๋ฉด) {
            	return false;
    		}
            
            ์ง€์šฐ๊ธฐ ์ „์— isTerminal false๋กœ ๋ฐ”๊ฟˆ;
            
            if (๋‹ค์Œ ๋…ธ๋“œ๊ฐ€ ์—†๋Š”๊ฒŒ ๋งž๋‹ค๋ฉด) {
            	ํ˜„์žฌ ๋…ธ๋“œ remove;
            }
        } else (index๊ฐ€ ์•„์ง ๋ฌธ์ž์—ด์˜ ๋๊นŒ์ง€ ์•ˆ๊ฐ”์œผ๋ฉด) {
    		if (delete(cur, str, index)๊ฐ€ false๋ผ๋ฉด) {
            	return false;
            }
            
            if (isTerminal์ด false์ด๊ณ , ๋‹ค์Œ ๋…ธ๋“œ๊ฐ€ ์—†๋Š”๊ฒŒ ๋งž๋‹ค๋ฉด) {
            	ํ˜„์žฌ ๋…ธ๋“œ remove;
            }
    	}
        return true;
    }

    โฑ๏ธ ํŠธ๋ผ์ด์˜ ์‹œ๊ฐ„๋ณต์žก๋„

    ์ œ์ผ ๊ธด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๋ฅผ N, ์ด ๋ฌธ์ž์—ด์˜ ์ˆ˜๋ฅผ M์ด๋ผ๊ณ  ํ•  ๋•Œ,

    • ์ƒ์„ฑ O(N*M)
    • ํƒ์ƒ‰ O(N)
    • ์‚ฝ์ž…๋งŒ O(N)

    ์ƒ์„ฑ์‹œ ๊ฐ€์žฅ ๊ธด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด N์„ M๋งŒํผ ๋„ฃ์–ด์•ผ ํ•˜๋‹ˆ O(N*M)

    ํƒ์ƒ‰์€ ๊ฐ€์žฅ ๊ธด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๋งŒํผ๋งŒ ํƒ์ƒ‰ํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— O(N)

    ์‚ฝ์ž…์€ ๋ฌธ์ž์—ด์„ ๋ฌธ์ž ํ•˜๋‚˜์”ฉ ๋„ฃ์œผ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๊ธด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด N๋งŒํผ์˜ O(N)