문자열의 집합 두 개 $S_C, S_N$가 주어진다. 각각 크기는 $C$, $N$이다. $Q$개의 문자열 쿼리를 받아서 그 문자열 $q$를 두 부분문자열 $c\in S_C$와 $n\in S_N$으로 분할 할 수 있는지 출력하는 문제이다.
접근
시간 제한 3초에 메모리 1024MB로 제한이 아주 넉넉하다. 백준 온라인 저지는 Python의 경우 여기에다가 추가로 메모리와 시간 제한을 늘려주기 때문에 11초 안에만 풀면 된다🤣
그래서… 예전에 Trie를 알기 전에는 딕셔너리를 사용하여 야매로 풀려고도 했었다.ㅋㅋ
어찌보면 당연하게도 문자열 슬라이싱을 너무 많이 하는 바람에 시간초과를 받았고, 결국 Trie를 공부해서 적용했다.
Trie의 경우 뭐 복잡한 것이 없다. 트리를 만드는데 타고 내려가면서 Prefix를 얻도록 잘 설계하자는 것이 끝이다. 딱 3개의 정보만 관리해주면 된다. 각 노드에 저장할 내용, 그리고 다음 노드가 무엇인지(트리 구조가 되도록), 이 노드에서 끝나는 문자열이 있는지이다.
풀이
나이브하게 딕셔너리를 만들고 잘라보면서 찾자! 는 생각은 시간에 걸렸고, Trie를 적용하기로 했으니 이제 풀이를 구체화해 보자. 쿼리가 들어오면 앞에서부터 한 글자씩 진행하면서 $S_C$로 구성한 Trie를 탐색한다…
그런데 그러면 뒷부분은 어떻게 검색해야 할까? $S_N$으로도 Trie를 구성해서 탐색해야 하나? 생각해보면 Prefix를 그대로 두면서 뒷부분을 붙인 경우를 탐색할때 빠른 것이 이 문제에서 사용하는 Trie의 장점이다. 헌데 뒷부분은 계속 Prefix가 바뀌므로 매번 새롭게 슬라이싱으로 복사해서 사용해야 하고, 그러면 사실상 딕셔너리를 사용하는 것과 다름이 없다.
해서! 나는 그냥 $S_N$에 대해서는 딕셔너리를 사용해버렸다. Best solution을 생각해보자면 아마 문자열을 뒤집어서 Trie를 만들고, 쿼리도 뒤집어서 처리하는 방법으로 두 문자열 집합을 모두 Trie구조로 할 수도 있을 것이다. 그러나 앞서 말했듯 Python은 11초라는 무지막지한 시간 제한이 있기 때문에, 부담없이 복사해버린 다음 딕셔너리에 있는지 확인했다. Trie를 두개 만드는 것보다 이쪽이 간단하다.