간단히 말해서
문제의 가장 빠른 해결책은 가능한 모든 문서의 시작 부분을 인식하는 REGEX 또는 FSA (finite state automaton)를 정의하는 것 같습니다 (거짓 긍정이 허용되며 실제로는 문서에 해당하지 않음). 그런 다음 입력에서 매우 빠르게 실행하여 문서가 거의 오류없이 시작될 수있는 다음 위치를 식별 할 수 있습니다. 문서 시작에 약간의 잘못된 위치가 발생할 수 있지만 파서가이를 인식하여 버립니다.
따라서 유한 상태 오토 마톤은 당신이 찾고 있던 파서 이름이 될 수 있습니다. :)
문제
특히 어휘가 많은 해석을 할 수있는 경우 실제 문제를 이해하는 것은 항상 어렵습니다. parse forest라는 단어는 여러 구문 분석 트리가있는 모호한 문장의 Context-Free (CF) 구문 분석을 위해 만들어졌습니다 (afaik). 문장의 격자를 구문 분석하거나 다른 유형의 문법으로 다소 일반화 할 수 있습니다. 따라서 Earley, GLR, Marpa 및이 경우에는 관련이없는 파생 파서 (많은 다른 것)에 대한 모든 대답이 있습니다.
그러나 그것은 분명히 당신이 생각하는 것이 아닙니다. 문서 의 구문이 정의되는 방식을 실제로 말하지 않기 때문에 모호하지 않은 문서의 시퀀스 인 고유 문자열을 구문 분석하고 각 또는 구조적 표현에 대한 구문 분석 트리를 얻으려고합니다. 공식적인 언어 관점. 문서의 시작 부분에서 시작할 때 구문 분석 작업을 수행하는 알고리즘과 테이블이 있습니다. 그러면 그렇게 해.
실제 문제는 문서 스트림에 문서를 분리하는 상당한 가비지가 포함되어 있다는 것입니다. 그리고 당신의 어려움은이 쓰레기를 충분히 빨리 스캔하는 것 같습니다. 현재 기술은 처음부터 시작하여 첫 번째 문자부터 스캔하고 전체 문서를 스캔 할 때까지 실패 할 때마다 다음 문자에서 다시 시작으로 건너 뛰는 것입니다. 그런 다음 문서가 방금 스캔 된 후 첫 문자부터 반복해서 진술합니다.
그것은 또한 그의 대답 의 두 번째 부분에서 @amon이 제안한 솔루션 입니다.
파서의 코드가 문서의 시작 부분에서 매우 효율적으로 시작되도록 최적화되지 않았기 때문에 매우 빠른 해결책은 아닙니다 (테스트 할 방법이 없습니다). 정상적인 사용에서는이 작업을 한 번만 수행하므로 최적화 관점에서 핫스팟이 아닙니다. 따라서이 솔루션에 대한 당신의 온화한 행복은 그리 놀라운 일이 아닙니다.
따라서 실제로 필요한 것은 대량의 쓰레기로 시작하는 문서의 시작 부분을 빠르게 찾을 수있는 알고리즘입니다. 운 좋게도 : 그러한 알고리즘이 존재합니다. 그리고 나는 당신이 그것을 알고 있다고 확신합니다 : 그것은 REGEX를 찾는 것입니다.
간단한 해결책
해야 할 일은 문서의 사양을 분석하여 이러한 문서가 시작되는 방법을 찾는 것입니다. 구문 사양이 공식적으로 어떻게 구성되어 있는지 잘 모르겠 기 때문에 정확히 어떻게 말할 수는 없습니다. 아마도 그들은 모두 유한 한 목록에서 나온 단어로 시작하고 구두점이나 숫자가 섞여있을 수 있습니다. 그것은 당신이 확인하기위한 것입니다.
FSA (Finite State Automaton)를 정의하거나 대부분의 프로그래머에게 문서의 처음 몇 문자를 인식 할 수있는 정규식 (REGEX)을 정의해야합니다. 큰 (시간과 공간이 걸릴 수 있음). 이는 문서 사양에서 비교적 쉽게 수행 할 수 있어야하며 문서 사양을 읽는 프로그램으로 자동으로 수행 할 수 있습니다.
정규 표현식을 작성한 후에는 입력 스트림에서 실행하여 다음과 같이 첫 번째 (또는 다음) 문서의 시작 부분으로 매우 빠르게 이동할 수 있습니다.
나는 가정 :
- docstart
모든 문서의 시작 부분과 일치하는 정규식입니다
- search(regex, stream)
함수가되는 검색한다 stream
일치하는 문자열에 대한 regex
. 리턴하면 스트림은 일치하는 첫 번째 하위 문자열의 시작 부분에서 시작하여 접미어 서브 스트림으로 줄어 듭니다. 또는 빈 스트림으로 일치하는 항목이 없습니다.
- parse(stream)
스트림의 시작 부분 (왼쪽에있는 것)에서 문서를 구문 분석하려고 시도하고 구문 분석 트리를 어떤 형식 으로든 리턴하거나 실패합니다. 리턴하면 스트림은 구문 분석 된 문서의 끝 바로 다음 위치에서 시작하여 접미어 서브 스트림으로 줄어 듭니다. 구문 분석에 실패하면 예외를 호출합니다.
forest = empty_forest
search(docstart, stream)
while stream is not empty:
try:
forest = forest + parse(stream)
except
remove first character from stream
search(docstart, stream)
첫 번째 문자를 제거해야 다음 검색에서 다시 일치하는 항목을 찾을 수 없습니다.
물론 스트림 단축은 이미지입니다. 스트림의 인덱스 일 수 있습니다.
마지막으로 정규식이 모든 시작을 인식하는 한 너무 정확할 필요는 없습니다. 때때로 문서의 시작이 될 수없는 문자열을 인식하면 (거짓 긍정적) 파서에 대한 쓸모없는 호출 비용은 유일한 페널티입니다.
따라서 가능하다면 정규 표현식을 단순화하는 데 도움이 될 수 있습니다.
더 빠른 솔루션의 가능성에 대해
위의 솔루션은 대부분의 경우에 잘 작동합니다. 그러나 처리 할 가비지와 테라 바이트 단위의 파일이 실제로 많은 경우 더 빠르게 실행되는 다른 알고리즘이있을 수 있습니다.
이 아이디어는 Boyer-Moore 문자열 검색 알고리즘 에서 파생됩니다 . 이 알고리즘은 문자열의 구조적 분석을 사용하여 대부분의 스트림 읽기를 건너 뛰고 조각을 보지 않고도 조각을 뛰어 넘기 때문에 단일 문자열을 매우 빠르게 검색 할 수 있습니다. 단일 문자열에 대해 가장 빠른 검색 알고리즘입니다.
어려운 점은 단일 문자열이 아닌 정규식 검색에 대한 적응이 매우 섬세하게 보이고 고려중인 정규식의 기능에 따라 제대로 작동하지 않을 수 있다는 것입니다. 이는 구문 분석중인 문서의 구문에 따라 달라질 수 있습니다. 그러나 내가 찾은 문서를주의 깊게 읽을 시간이 없었기 때문에 이것을 너무 많이 믿지 마십시오.
나는 분명히 참조 된 연구 논문을 포함하여 웹에서 찾은 하나 또는 두 개의 포인터로 당신 을 떠날 것 입니다 . 그리고 그것을 할 선반 프로그램이 없을 것입니다.