2. • 패턴 집합에 대한 매칭 알고리즘
패턴이 1개라면 KMP Algorithm으로 선형에 해결
하지만 KMP는 패턴 개수에 비례하여 시간복잡도가 증가
O(m+zn) (m : 패턴들의 길이 합, z : 패턴 수, n : text 크기)
Aho-Corasick은 O(m + n + k)의 시간 복잡도로 패턴 집합에
대하여 패턴 길이와 텍스트의 선형 시간에 탐색을 처리할 수
있어요.(k : 텍스트 내에 패턴의 발생 수)
Aho-Corasick
3. • 크게 3단계로 나눌 수 있어요.
1. 패턴 string들에 대한 Trie(트라이) 구성
2. Failure Link와 Output Link 구성
3. Matching
Aho-Corasick
4. • 패턴 string 각각에 대해 Trie의 노드들을 따라가다가 갈
곳이 없다면 새로운 노드를 추가하는 방식으로 구성하면
됩니다. - O(m)
• 예를 들어 패턴이 {“ab”, “c”, “a”, “acd”}라면 다음과 같은
Trie가 구성이 되겠죠. 테두리가 빨간 노드들은 그곳에서
끝나는 패턴 string이 있습니다.
• Trie 구성 끝!
1. Trie
5. • 방금 구성한 Trie를 이용해 Failure Link의 필요성을
알아보겠습니다.
• Text가 “acabacd”이고, 우리는 이 텍스트에 등장하는 패턴
string들을 모두 알고 싶습니다.
Text : “acabacd”
Text의 처음 문자가 a이므로
Trie에서 a에 해당하는 노드로
이동합니다.
2. Failure Link
7. Text : “acabacd”
다음 문자가 a이므로 Trie에서 a에 해당하는 노드로 이동해야
하는데, Trie에는 그런 노드가 존재하지 않습니다.
이전에는 첫 번째 문자인 a부터 탐색을
했으니 이젠 Trie의 루트로 돌아가서
두 번째 문자인 c에서부터 다시 탐색해야
할까요?
2. Failure Link
8. 이전까지 Trie에서 지나온 경로들을 이용해 새로 탐색을
시작할 노드의 위치를 빠르게 알 수는 없을까?
라는 물음에서 Failure Link가 등장하게 됩니다.
앞의 경우에는 c라는 노드에서 새로 탐색을
시작하면 되고, 이 노드로 연결해주는
간선을 Failure Link라고 합니다.
2. Failure Link
9. Failure Link는 다음과 같은 과정으로 만들 수 있습니다.
1. Trie의 루트로부터 BFS를 수행하면서 Failure Link를
만든다.
2. 현재 위치(p)와 가리키는 노드(q)에 대해서
1) p가 루트라면, q의 Failure Link는 루트이다.
2) p가 루트가 아니면, p의 실패 링크(pf)에서 q와 같은
문자로 이어지는 노드(r)가 있는지 확인한다.
(1) 그런 r이 존재한다면 qf는 r을 가리킨다.
(2) 그런 r이 존재하지 않는다면, p에 pf를 대입하고
1)로 돌아가 과정을 반복한다.
2. Failure Link
10. • 처음에 예시로 들었던 Trie에서 Failure Link를 구성해
보겠습니다.
• 루트에서 BFS를 수행하면서 시작해 봅시다.
2. Failure Link
11. • BFS 중 현재 위치 p는 Trie의 루트 노드입니다.
• 루트가 가리키는 노드 a와 c는 루트가 가리키는
노드들이므로 Failure Link가 루트입니다.
• Failure Link는 붉은선으로 표시하겠습니다.
2. Failure Link
12. • BFS 중 현재 위치 p는 루트가 가리키는 노드 a입니다.
• p가 가리키는 노드 b(= q)를 보겠습니다.
• p의 Failure Link가 가리키는 Trie의 루트(=pf)는 문자 b를
가리키는 노드(r)가 없습니다.
2. Failure Link
13. • 따라서 p에다가 pf를 대입하고 다시 생각해보겠습니다.
• 현재 위치 p는 루트가 되었습니다.
• p가 루트이므로 q의 Failure Link는 루트(=qf)입니다.
2. Failure Link
14. • BFS 중 현재 위치 p는 루트가 가리키는 노드 a입니다.
• p가 가리키는 노드 c(= q)를 보겠습니다.
• p의 Failure Link가 가리키는 Trie의 루트(=pf)는 문자 c를
가리키는 노드(r)가 있으므로 qf는 r을 가리킵니다.
2. Failure Link
15. • BFS 중 현재 위치 p는 루트가 가리키는 노드 c입니다.
• p가 가리키는 노드가 없으므로 p에 대한 작업은 끝.
2. Failure Link
16. • BFS 중 현재 위치 p는 루트가 가리키는 노드 c입니다.
• p가 가리키는 노드가 없으므로 p에 대한 작업은 끝.
2. Failure Link
17. • BFS 중 현재 위치 p는 노드 a가 가리키는 노드 c입니다.
• p가 가리키는 노드 d(= q)를 보겠습니다.
• p의 Failure Link가 가리키는 노드 c(=pf)는 문자 d를
가리키는 노드(r)가 없습니다.
2. Failure Link
18. • 따라서 p에다가 pf를 대입하고 다시 생각해보겠습니다.
• 현재 위치 p는 노드 c가 되었습니다.
• p의 Failure Link가 가리키는 Trie의 루트(=pf)는 문자 d를
가리키는 노드(r)가 없습니다.
2. Failure Link
19. • 따라서 p에다가 pf를 대입하고 다시 생각해보겠습니다.
• 현재 위치 p는 루트가 되었습니다.
• p가 루트이므로 q의 Failure Link는 루트(=qf)입니다.
2. Failure Link
20. • 예시로 든 패턴의 Trie와 Failure Link 최종 모습입니다.
2. Failure Link
21. • 패턴들 중에 다른 패턴의 substring인 string이 존재하게
되면 Text에 등장하는 모든 패턴들을 탐색하지 못 할 수가
있어요.
• 이를 막기 위하여 출력 링크(Output Link)라는 자료 구조를
추가하게 됩니다.
• 처음에 각각의 패턴 string들이 끝이 나는 정점은 그 정점을
Sucess Link로 가지게 됩니다
2. Output Link(Output Link)
22. • BFS 도중, 현재 정점에서 Failure link를 따라 가서 패턴이
끝이 나게 되면 여러 단계의 Failure link를 무시하고 바로 그
정점으로 Output Link를 연결해주면 됩니다.
• Failure link를 추가할 때, 같이 Failure Link를 따라간 정점이
패턴의 끝이면 그 정점으로 Output Link를 연결해주고
그렇지 않으면 그 정점의 Output Link를 가져오면 됩니다.
2. Output Link(Output Link)
23. • 예시로 든 패턴의 Trie, Failure Link와 Output Link(푸른
간선)의 최종 모습이에요. 노드 안에 푸른 원이 있는 것은
자기 자신을 Output Link가 가리킨다는 표시입니다.
2. Output Link(Output Link)
24. • Text의 글자와 Trie의 노드에서 나가는 간선의 글자와
비교하면서 일치하면 해당 정점으로 이동하게 됩니다.
• 이동하면서 Output Link가 존재하는지 확인을 계속하고
Output Link가 존재하면 패턴이 발생했음을 의미합니다.
• 비교하다가 틀리게 되면 Failure link를 따라 가서 계속
글자를 비교해 주면서 탐색을 하게 됩니다.
• Text의 각 문자를 한 번 확인하였으면 다시 확인하지 않게
되고 따라서 O(m + n + k)의 시간 복잡도로 처리가
가능하게 됩니다. (m : 패턴들의 길이 합, n : Text의 길이,
k : 텍스트 내에 패턴의 발생 수)
3. Matching
25. • Text가 “dabcacdfc”라고 해보겠습니다.
• 앞서 구한 걸 이용해서 이 Text에 등장하는 모든 패턴
string들을 구해볼게요.
3. Matching
26. Text : dabcacdfc
현재 위치(p)는 트라이의 루트 노드입니다. p에서 d로 가는
노드가 없는데, p가 루트이므로 다음 Text 원소를 보죠.
3. Matching
27. Text : dabcacdfc
현재 위치(p)는 트라이의 루트 노드입니다. p에서 a로 가는
노드가 있으므로 갑니다. 그런데 노드 a에서 Output Link가
존재하네요!
3. Matching
28. Text : dabcacdfc
Text에 존재하는 패턴 string 중 하나인 “a”를 찾았습니다.
다음 Text 원소인 b를 보겠습니다.
3. Matching
29. Text : dabcacdfc
현재 위치 p에서 Output Link가 존재하네요!
Text에 존재하는 패턴 string 중 하나인 “ab”를 찾았습니다.
3. Matching
38. Text : dabcacdfc
현재 위치 p에 Output Link가 있습니다. “acd”가 Text에
존재하네요. Text의 다음 문자 f를 보았는데 p에서 나가는
간선이 없어서 실패링크를 타고 루트로 갑니다.
3. Matching
39. Text : dabcacdfc
루트에서도 f로 나가는 간선이 없으므로 Text의 다음 문자 c를
봅니다. p에서 나갈 수 있는 간선이 있으므로 갑니다.
3. Matching
40. Text : dabcacdfc
현재 위치 p가 있는 곳에 Output Link가 있네요. “c”를
찾았습니다. Text의 다음 문자가 없으므로 매칭이 종료됩니다.
3. Matching
41. 앞서 보여드린 예시에서는 Output Link를 여러 번 따라가는
경우가 없었습니다.
만약 어떤 노드에서 Output Link가 존재하고 그 Link를
따라갔는데, 그 노드에서 또 Output Link가 존재한다면, 다른
패턴이 존재한다는 의미입니다. Output Link가 존재하지 않을
때까지 계속 따라가주면 됩니다.
3. Matching
42. 감사합니다.
참고 : ‘프로그래밍 대회에서 배우는 알고리즘 문제 해결 전략 2권’, 구종만
위키피디아 – 아호 코라식 알고리즘
End