내 청중의 PCI 감사자를위한 약간의 치료 컴퓨터 과학.
나는 당신에게 임의의 정수 배열을 건네줍니다. 세 번째 숫자가 있는지 어떻게 알 수 있습니까?
분명한 방법이 있습니다.“3”을 찾거나 배열을 소진 할 때까지 숫자를 순차적으로 확인하십시오. 선형 검색. 10 개의 숫자가 주어지면 10 단계를 취할 수 있다고 가정해야합니다. N 숫자, N 단계.
그림 1.png
선형 검색이 잘못되었습니다. 선형보다 악화하기가 어렵습니다. 그것을 개선합시다. 배열을 정렬하십시오.
그림 2.png
정렬 된 배열은 다른 전략을 제안합니다. 배열의 중간으로 이동하여 찾고있는 값이 작거나 (왼쪽) 또는 큰 (오른쪽)인지 확인하십시오. 값을 찾을 때까지 배열을 반으로 자릅니다.
이진 검색. 10 개의 숫자가 주어지면 정렬 된 배열에서 이들 중 하나를 찾는 데 최대 3 단계 (-log2 of 10)가 필요합니다. O (log n) 검색은 훌륭합니다. 65,000 개의 요소가 있다면 그 중 하나를 찾기 위해 16 단계 만 수행하면됩니다. 요소를 두 배로 늘리면 17 단계입니다.
그러나 정렬 된 배열은 빨라집니다. 우선, 정렬은 선형 검색보다 비쌉니다. 따라서 이진 검색을 많이 사용하지 않습니다. 대신 이진 트리를 사용합니다.
그림 3.png
이진 트리를 검색하려면 맨 위에서 시작하여“내 키가 현재 노드보다 작거나 (왼쪽) 또는 더 큽니다 (오른쪽)”라고 묻고 ok, ok, ok까지 반복하십시오. 그러나 그 나무는 예쁘지 않습니까?
(균형) 이진 트리를 사용한 검색은 이진 검색과 같이 O (log n)이며 트리의 요소 수에 따라 다릅니다. 이진 트리는 훌륭합니다. 빠른 조회와 정렬 된 순회, 해시 테이블에서 얻지 못하는 것입니다. 이진 트리는 해시 테이블보다 더 나은 기본 테이블 구현입니다. 2.
그러나 이진 트리 만이 트리 구조의 조회 메커니즘이 아닙니다. PATRICIA 트리라고도하는 이진 기수는 하나의 근본적인 차이점을 가진 이진 트리처럼 작동합니다. 각 노드에서보다 큼 /보다 큼을 비교하는 대신 비트가 설정되어 있는지 확인하고, 설정되어 있으면 오른쪽으로 분기하고 설정되어 있지 않으면 왼쪽으로 분기합니다.
그림 4.png
이진 기수가 어떻게 작동하는지에 대해 많이 배제하고 있습니다. 기수 시도가 문서화되지 않은 것으로 악명이 높기 때문에 이는 수치스러운 일입니다.-Sedgewick은“알고리즘”에서 악명 높은 것으로 유명해졌으며 Wikipedia 페이지는 그 결과를 망쳤습니다. 사람들은 여전히 무엇을 부를 것인지에 대해 논쟁합니다! 백 링크 및 비트 위치 레이블이 지정된 가장자리에 대한 설명 대신 작은 Ruby 구현이 있습니다.
기수 시도가 멋진 이유는 다음과 같습니다.
Search performance varies with the key size, not the number of elements in the tree. With 16 bit keys, you’re guaranteed 16 steps
균형을 맞추지 않고 트리의 요소 수에 관계없이
More importantly, radix tries give you lexicographic matching, which is a puffed-up way of saying “search with trailing wildcard”, or
“명령 줄 완성 스타일 검색”. 기수 트리에서 "ro *"를 빠르게 검색하고 "rome"과 "romulous"및 "roswell"을 얻을 수 있습니다.
삼.
당신을 잃었습니다.
이것을 문맥에 넣어 봅시다. 시도는 인터넷 라우팅을위한 중요한 데이터 구조입니다. 라우팅 문제는 다음과 같습니다.
You have a routing table with entries for “10.0.1.20/32 -> a” and “10.0.0.0/16 -> b”.
You need packets for 10.0.1.20 to go to “a”
You need packets for 10.0.1.21 to to to “b”
이것은 기본 이진 트리로는 해결하기 어려운 문제이지만 기수 트리에서는 "1010.0000.0000.0000.0000.0001.0100"(10.0.1.20의 경우)과 "1010"(10.0.0.0의 경우) 만 요구합니다. ). 사전 검색은 라우팅에“최적의 일치”를 제공합니다. 위의 루비 코드에서 시도해 볼 수 있습니다. trie에 *”10.0.0.0”.to_ip를 추가하고“10.0.0.1”.to_ip를 검색하십시오.
라우팅과 기수 간의 대응 관계가 매우 강해서 가장 인기있는 범용 기수 라이브러리 (CPAN의 라이브러리)가 실제로 GateD에서 도난당했습니다. 그건 그렇고 혼란스럽고 사용하지 마십시오.
trie의 작동 방식을 이해하면 정규식의 작동 방식도 이해합니다. Tries는 결정 론적 유한 오토마타 (DFA)의 특별한 경우로, 분기는 비트 비교만을 기반으로하며 항상 분기 전달입니다. 좋은 정규식 엔진은 더 많은 "기능"을 가진 DFA를 처리하는 것입니다. 내 그림이 당신에게 의미가 있다면, 톰슨의 NFA-DFA 감소 알고리즘에 대한이 훌륭한 기사의 그림들도 그 기사가 더 똑똑해질 것입니다. 4.
백본 ISP의 네트워크 운영자입니다. 귀하의 세계는 크게“접두사”—- IP 네트워크 / 넷 마스크 쌍으로 구성됩니다. 해당 접두사의 네트 마스크는 매우 중요합니다. 예를 들어, 121/8은 한국에 속합니다. 121.128 / 10은 한국 통신에 속하고 121.128.10 / 24는 KT 고객에 속하며 121.128.10.53은 해당 고객 내부에있는 하나의 컴퓨터입니다. 봇넷이나 스팸 작업 또는 웜 전파를 추적하는 경우 해당 넷 마스크 번호가 매우 중요합니다.
안타깝게도 IP 패킷에는 "넷 마스크"가 표시되어 있지 않습니다. 넷 마스크는 전체적으로 구성 세부 사항입니다. 따라서 트래픽을보고있을 때 기본적으로이 데이터를 사용하여 작업 할 수 있습니다.
ips.png
놀랍게도 볼 패킷이 충분하면 넷 마스크를 추측하기에 충분한 정보입니다. 소니에서 일하는 동안, Kenjiro Cho는 시도를 바탕으로 그렇게하는 우아한 방법을 생각해 냈습니다. 방법은 다음과 같습니다.
소프트웨어 라우터가 사용하는 것과 같은 기본 이진 기수를 사용하십시오. 그러나 트리의 노드 수를 10,000으로 제한했습니다. 백본 링크에서 IP 헤더에서 주소를 기록하면 10,000 개의 노드가 순식간에 소모됩니다.
노드 목록을 LRU 순서로 정렬 된 목록에 저장하십시오. 다시 말해, IP 주소를 노드와 일치 시키면 노드를 "터치"하여 목록의 맨 위에 고정시킵니다. 점차적으로 자주 보이는 주소는 맨 위로 올라가고 드물게 보이는 노드는 맨 아래로 내려갑니다.
그림 6.png
이제 속임수입니다. 노드가 부족하고 새 노드가 필요한 경우 목록 맨 아래에서 교정하십시오. 그러나 그렇게하면 다음과 같이 노드에서 부모로 데이터를 롤업합니다.
그림 5.png
10.0.1.2 및 10.0.1.3은 형제 / 32이며, 두 부분은 10.0.1.2/31입니다. 그것들을 되 찾으려면 10.0.1.2/31로 병합하십시오. 10.0.1.2/31을 회수해야하는 경우 10.0.1.0/31과 병합하여 10.0.1.0/30을 형성 할 수 있습니다.
이 작업을 1 분 이상 반복하면 눈에 띄는 소스가 LRU 목록의 맨 위에 머물면서 트리에서 자신의 위치를 방어하고 주변의 / 32 노이즈는 / 0까지 버블 링합니다. 100 개의 노드 트리를 가진 위의 IP의 원시 목록에 대해 이것을 얻습니다.
조는 이것을 휴리스틱 아구 리라고 부릅니다. 5.
Aguri는 BSD 라이센스입니다. Cho의 오래된 홈페이지에서 pcap을 통해 패킷을 감시하는 드라이버 프로그램과 드라이버 프로그램을 다운로드 할 수 있습니다. 6.
나는 이것으로 어딘가에 가고 있지만, 지금이 게시물에 1300 단어가 있습니다. 알고리즘 인 사람이라면 지금까지 나에게 지 쳤고, 그렇지 않으면 안됩니다. 지금. 아 구리가 잠깐 들어 오면 이번 주 후반에 시원하고 쓸모없는 것을 줄 게요.
거기에 수많은 링크가 흩어져 있습니다. 불행히도, Archive.org는 이미지만을 유지하지 않고 텍스트 만 보관하므로 일부 이미지가 손실되었습니다. 보관 된 것들은 다음과 같습니다.