Tóm lại
Dường như giải pháp nhanh cho vấn đề của bạn là xác định REGEX hoặc FSA (máy tự động trạng thái hữu hạn), nhận ra tất cả các khởi đầu có thể của tài liệu (cho phép dương tính giả, điều đó thực sự không tương ứng với tài liệu). Sau đó, bạn có thể chạy nó rất nhanh trên đầu vào của mình để xác định vị trí tiếp theo nơi tài liệu có thể bắt đầu với một vài lỗi. Nó có thể gây ra một vài vị trí sai lầm khi bắt đầu tài liệu, nhưng chúng sẽ được trình phân tích cú pháp nhận ra và từ bỏ.
Vì vậy, Finite State Automaton có thể là tên trình phân tích cú pháp mà bạn đang tìm kiếm. :)
Vấn đề
Luôn luôn khó hiểu một vấn đề thực tế, đặc biệt là khi từ vựng có thể có nhiều cách giải thích. Rừng phân tích cú pháp được đặt ra (afaik) để phân tích ngữ cảnh không có ngữ cảnh (CF) cho các câu mơ hồ có nhiều phân tích cú pháp. Nó có thể được khái quát phần nào để phân tích một mạng các câu hoặc các loại ngữ pháp khác. Do đó, tất cả các câu trả lời về Earley, GLR, Marpa và các trình phân tích cú pháp phái sinh (có nhiều câu trả lời khác) không liên quan trong trường hợp này.
Nhưng đó rõ ràng không phải là những gì bạn có trong tâm trí. Bạn muốn phân tích một chuỗi duy nhất là một chuỗi các tài liệu không rõ ràng và lấy một cây phân tích cho mỗi chuỗi , hoặc một loại biểu diễn có cấu trúc nào đó, vì bạn không thực sự nói cách xác định cú pháp của tài liệu của bạn, nó nằm ở đâu một quan điểm ngôn ngữ chính thức. Những gì bạn có là một thuật toán và các bảng sẽ thực hiện công việc phân tích cú pháp khi bắt đầu ở phần đầu của tài liệu. Vì vậy, nó được.
Vấn đề thực tế là luồng tài liệu của bạn chứa rác đáng kể ngăn cách các tài liệu. Và dường như khó khăn của bạn là quét rác này đủ nhanh. Kỹ thuật hiện tại của bạn là bắt đầu từ đầu và cố gắng quét từ ký tự đầu tiên và bỏ qua để khởi động lại ở ký tự tiếp theo bất cứ khi nào nó thất bại, cho đến khi bạn quét toàn bộ tài liệu. Sau đó, bạn lặp lại nêu từ ký tự đầu tiên sau khi tài liệu vừa được quét.
Đó cũng là giải pháp được đề xuất bởi @amon trong phần thứ hai của câu trả lời của ông .
Nó có thể không phải là một giải pháp rất nhanh (tôi không có cách nào để kiểm tra), vì không chắc là mã của trình phân tích cú pháp được tối ưu hóa để bắt đầu rất hiệu quả khi bắt đầu một tài liệu. Trong sử dụng bình thường, nó chỉ thực hiện điều này một lần, do đó nó không phải là điểm nóng theo quan điểm tối ưu hóa. Do đó, hạnh phúc vừa phải của bạn với giải pháp này không quá ngạc nhiên.
Vì vậy, những gì bạn thực sự cần là một thuật toán có thể nhanh chóng tìm thấy sự khởi đầu của một tài liệu bắt đầu với một khối rác. Và bạn thật may mắn: những thuật toán như vậy có tồn tại. Và tôi chắc chắn bạn biết điều đó: nó được gọi là tìm kiếm REGEX.
Giải pháp đơn giản
Những gì bạn phải làm là phân tích đặc điểm kỹ thuật của tài liệu của bạn để tìm cách các tài liệu này bắt đầu. Tôi không thể chính xác cho bạn biết làm thế nào, vì tôi không chắc cách thức đặc tả cú pháp của chúng được tổ chức chính thức. Có thể tất cả đều bắt đầu bằng một số từ trong danh sách hữu hạn, có thể trộn lẫn với một số dấu câu hoặc số. Đó là để bạn kiểm tra.
Những gì bạn phải làm là xác định một máy tự động trạng thái hữu hạn (FSA) hoặc tương đương với hầu hết các lập trình viên một biểu thức chính quy (REGEX) có thể nhận ra một vài ký tự đầu tiên của tài liệu: càng nhiều, càng tốt, nhưng nó không cần phải rất lớn (vì điều đó có thể mất thời gian và không gian). Điều này tương đối dễ thực hiện từ đặc điểm kỹ thuật của tài liệu của bạn và có thể được thực hiện tự động với chương trình đọc thông số kỹ thuật của tài liệu của bạn.
Khi bạn đã tạo regrec của mình, bạn có thể chạy nó trên luồng đầu vào của mình để nhanh chóng bắt đầu tài liệu đầu tiên (hoặc tiếp theo) như sau:
Tôi giả sử:
- docstart
là một biểu thức chính phù hợp với phần đầu của tất cả các tài liệu
- search(regex, stream)
là một hàm tìm kiếm stream
một chuỗi con phù hợp regex
. Khi nó trở lại, luồng được giảm xuống thành dòng phụ hậu tố bắt đầu từ đầu chuỗi con phù hợp đầu tiên hoặc luồng trống không tìm thấy kết quả khớp.
- parse(stream)
cố gắng phân tích tài liệu từ đầu luồng (phần còn lại của nó) và trả về cây phân tích theo bất kỳ định dạng nào hoặc không thành công. Khi nó trở lại, luồng được giảm xuống thành dòng phụ hậu tố bắt đầu tại vị trí ngay sau phần cuối của tài liệu được phân tích cú pháp. Nó gọi một ngoại lệ nếu phân tích cú pháp thất bại.
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)
Lưu ý rằng việc loại bỏ ký tự đầu tiên là cần thiết để tìm kiếm tiếp theo sẽ không tìm thấy lại cùng một kết quả.
Tất nhiên, rút ngắn luồng là một hình ảnh. Nó có thể chỉ là một chỉ mục trên luồng.
Một lưu ý cuối cùng là regex của bạn không cần phải quá chính xác, miễn là nó nhận ra tất cả sự khởi đầu. Nếu đôi khi nó nhận ra một chuỗi không thể là phần đầu của tài liệu (dương tính giả), thì hình phạt duy nhất là chi phí của một cuộc gọi vô dụng đến trình phân tích cú pháp.
Vì vậy, điều đó có thể giúp đơn giản hóa regex, nếu hữu ích.
Về khả năng của một giải pháp nhanh hơn
Các giải pháp trên nên hoạt động khá tốt trong hầu hết các trường hợp. Tuy nhiên, nếu bạn thực sự có rất nhiều rác và terabyte tệp để xử lý, có thể có các thuật toán khác chạy nhanh hơn.
Ý tưởng được bắt nguồn từ thuật toán tìm kiếm chuỗi Boyer-Moore . Thuật toán này có thể tìm kiếm một luồng cho một chuỗi cực nhanh vì nó sử dụng phân tích cấu trúc của chuỗi để bỏ qua việc đọc hầu hết luồng, nhảy qua các đoạn mà không cần nhìn vào chúng. Đây là thuật toán tìm kiếm nhanh nhất cho một chuỗi.
Khó khăn là sự thích ứng của nó với regex tìm kiếm, thay vì một chuỗi đơn lẻ, có vẻ rất tinh vi và có thể không hoạt động tốt, tùy thuộc vào các tính năng của regex bạn đang xem xét. Điều đó có thể lần lượt phụ thuộc vào cú pháp của các tài liệu bạn đang phân tích cú pháp. Nhưng đừng tin tôi quá nhiều về điều này vì tôi không có thời gian để đọc kỹ các tài liệu tôi tìm thấy.
Tôi sẽ để lại cho bạn một hoặc hai con trỏ tôi tìm thấy trên web, bao gồm một tài liệu rõ ràng là một tài liệu nghiên cứu được giới thiệu , nhưng bạn nên xem đây là suy đoán nhiều hơn, có thể là nghiên cứu, chỉ được xem xét nếu bạn gặp vấn đề về hiệu suất mạnh. Và có lẽ không có chương trình kệ nào sẽ làm điều đó.