article thumbnail image
Published 2021. 11. 16. 13:52

문제 설명

문제 설명

http://icpc.me/5446

 

5446번: 용량 부족

팀포2 덕후 연수는 팀포2를 다운받던 도중 하드 용량이 부족하다는 것을 알았다. 이때는 침착하게 팀포2를 하지 말거나 하드를 새로 사면 되지만 불가능했고, 결국 하드에서 쓸모없는 파일을 지

www.acmicpc.net

풀이

트라이를 이용해서 풀 수 있다.

트라이에 문자열을 삽입할 때, 지워야 하는 문자열이 끝날 때, 지워야 하는 문자인지, 지우면 안 되는 문자인지를 체크하며 삽입을 한다.

그럼 어떠한 한 노드의 상황 3가지이다.

1. 지워야 하고, 지워도 되는 상황 -> 자식 노드까지 한 번에 지워버린다

2. 지우면 안 되면서, 어떤 지워야 하는 문자열의 마지막 문자인 상황 -> *없이 rm abc와 같이 지운다

3. 지워야 하지만 지우면 안 되는 상황 -> 자식 노드로 이동하여 rm ~~*로 지울 수 있는지 확인

cf) N2가 0이면 지우면 안 되는 파일이 없기 때문에 rm *로 모두 지워도 된다.

코드

#include <cstdio>
#include <cstring>
#include <unordered_map>

using namespace std;

struct Trie {
    unordered_map<char, Trie*> nxt;
    bool dontDel;
    bool doDel;
    bool doDelEnd;
    Trie() : dontDel(false), doDel(false), doDelEnd(false) { }
    ~Trie() {  for (auto &[c, trie] : nxt) delete trie; }
    
    void insert(const char *s, bool flag) {
        if (*s == 0) return;
        if (!nxt.count(*s)) nxt[*s] = new Trie();
        
        if (flag) nxt[*s] -> dontDel = true;
        else nxt[*s] -> doDel = true;

        if (!flag && *(s + 1) == 0) {
            nxt[*s] -> doDelEnd = true;
            return;
        }
        nxt[*s] -> insert(s + 1, flag);
    }

    int find() {
        bool flag = true;
        int ret = 0;
        for (auto &[c, trie]: nxt) if (trie -> doDel) {
        	// 1번 상황
            if (!(trie -> dontDel)) ret++;
            // 2번 상황
            if (trie -> doDelEnd && trie -> dontDel) ret++;
            // 3번 상황
            if (trie -> dontDel) ret += trie -> find();
        }        
        return ret;
    }
};

void solve() {
    Trie *root = new Trie();
    int n1; scanf("%d", &n1);
    for (int i = 0; i < n1; i++) {
        char s[22]; scanf("%s", s);
        root -> insert(s, false);
    }
    int n2; scanf("%d", &n2);
    for (int i = 0; i < n2; i++) {
        char s[22]; scanf("%s", s);
        root -> insert(s, true);
    }
    printf("%d\n", n2 ? root -> find() : 1);
    delete root;
}

int main() {
    int t; scanf("%d", &t);
    while (t--) solve();
}

'Algorithm > BOJ' 카테고리의 다른 글

백준[2243] 사탕상자  (0) 2021.11.17
백준[16927] 배열 돌리기 2  (0) 2021.11.16
백준[17831] 대기업 승범이네  (0) 2021.11.15
백준[19581] 두 번째 트리의 지름  (2) 2021.11.15
백준[16978] 수열과 쿼리 22  (0) 2021.11.13
복사했습니다!