โดยสังเขป
ดูเหมือนว่าวิธีแก้ปัญหาอย่างรวดเร็วของคุณคือการกำหนด REGEX หรือ FSA (สถานะออโตเมติก จำกัด ) ที่รับรู้จุดเริ่มต้นที่เป็นไปได้ทั้งหมดของเอกสาร (อนุญาตบวกเท็จซึ่งไม่ตรงกับเอกสาร) จากนั้นคุณสามารถเรียกใช้มันอย่างรวดเร็วในการป้อนข้อมูลของคุณเพื่อระบุสถานที่ต่อไปที่เอกสารอาจเริ่มต้นด้วยข้อผิดพลาดเล็กน้อย มันอาจทำให้เกิดตำแหน่งที่ผิดพลาดเล็กน้อยสำหรับการเริ่มต้นเอกสาร แต่ parser จะถูกจดจำและถูกละทิ้ง
ดังนั้นAutomite Stateอาจเป็นชื่อ parser ที่คุณต้องการ :)
ปัญหา
เป็นการยากที่จะเข้าใจปัญหาที่เกิดขึ้นจริงโดยเฉพาะเมื่อคำศัพท์อาจมีการตีความมากมาย คำว่าแจงป่าถูกประกาศเกียรติคุณ (afaik) สำหรับการแยกบริบทฟรี (CF) ของการแยกประโยคที่ไม่ชัดเจนที่มีต้นไม้แยกหลาย มันสามารถวางนัยทั่วไปในการแยกวิเคราะห์ประโยคของประโยคหรือไวยากรณ์ประเภทอื่น ๆ ดังนั้นคำตอบทั้งหมดเกี่ยวกับ Earley, GLR, Marpa และ parsers อนุพันธ์ (มีอื่น ๆ อีกมากมาย) ที่ไม่เกี่ยวข้องในกรณีนี้
แต่นั่นไม่ใช่สิ่งที่คุณมีอยู่ในใจ คุณต้องการแยกสตริงที่ไม่ซ้ำกันซึ่งเป็นลำดับของเอกสารที่ไม่คลุมเครือและรับการแยกวิเคราะห์ต้นไม้สำหรับแต่ละโครงสร้างหรือการแทนโครงสร้างบางประเภทเนื่องจากคุณไม่ได้พูดจริง ๆ ว่ามีการกำหนดไวยากรณ์ของเอกสารของคุณไว้ที่ใด มุมมองภาษาอย่างเป็นทางการ สิ่งที่คุณมีคืออัลกอริทึมและตารางที่จะทำการแยกวิเคราะห์เมื่อเริ่มต้นที่จุดเริ่มต้นของเอกสาร ดังนั้นไม่ว่าจะเป็น
ปัญหาที่แท้จริงคือสตรีมเอกสารของคุณมีขยะจำนวนมากที่แยกเอกสาร และดูเหมือนว่าความยากของคุณคือการสแกนขยะนี้เร็วพอ เทคนิคปัจจุบันของคุณคือการเริ่มต้นที่จุดเริ่มต้นและพยายามสแกนจากอักขระตัวแรกและข้ามไปที่การรีสตาร์ทที่อักขระตัวถัดไปทุกครั้งที่มันล้มเหลวจนกว่าคุณจะได้รับเอกสารทั้งหมด จากนั้นให้คุณระบุซ้ำจากตัวอักษรตัวแรกหลังจากเอกสารเพิ่งสแกน
ที่ยังเป็นวิธีการแก้ปัญหาโดย @amon ในส่วนที่สองของคำตอบของเขา
อาจไม่ใช่วิธีแก้ปัญหาที่รวดเร็วมาก (ฉันไม่มีวิธีทดสอบ) เนื่องจากไม่น่าเป็นไปได้ที่โค้ดของตัวแยกวิเคราะห์จะได้รับการปรับให้เหมาะกับการเริ่มต้นอย่างมีประสิทธิภาพมากในตอนต้นของเอกสาร ในการใช้งานปกติจะทำได้เพียงครั้งเดียวเท่านั้นดังนั้นจึงไม่ใช่จุดที่น่าสนใจจากมุมมองการปรับให้เหมาะสมที่สุด ดังนั้นความสุขปานกลางของคุณด้วยวิธีนี้จึงไม่น่าแปลกใจ
ดังนั้นสิ่งที่คุณต้องการจริงๆคืออัลกอริทึมที่สามารถค้นหาจุดเริ่มต้นของเอกสารที่ขึ้นต้นด้วยขยะจำนวนมากได้อย่างรวดเร็ว และคุณโชคดี: มีอัลกอริธึมดังกล่าวอยู่ และฉันแน่ใจว่าคุณรู้มันมันถูกเรียกว่าค้นหา REGEX
ทางออกที่ง่าย
สิ่งที่คุณต้องทำคือการวิเคราะห์ข้อมูลจำเพาะของเอกสารของคุณเพื่อค้นหาว่าเอกสารเหล่านี้เริ่มต้นอย่างไร ฉันไม่สามารถบอกคุณได้อย่างแน่นอนว่าฉันไม่แน่ใจว่าข้อกำหนดคุณลักษณะไวยากรณ์ของพวกเขาถูกจัดอย่างเป็นทางการอย่างไร อาจเป็นไปได้ว่าพวกเขาทั้งหมดเริ่มต้นด้วยคำบางคำจากรายการที่ จำกัด อาจผสมกับเครื่องหมายวรรคตอนหรือตัวเลข นั่นคือให้คุณตรวจสอบ
สิ่งที่คุณต้องทำคือการกำหนดสถานะ จำกัด อัตโนมัติ (FSA) หรือเทียบเท่าสำหรับโปรแกรมเมอร์ส่วนใหญ่นิพจน์ปกติ (REGEX) ที่สามารถรับรู้อักขระสองสามตัวแรกของเอกสาร: ยิ่งดี แต่ไม่จำเป็นต้องมาก ใหญ่ (เนื่องจากอาจต้องใช้เวลาและพื้นที่) สิ่งนี้ควรจะทำได้ง่าย ๆ จากข้อกำหนดของเอกสารของคุณและสามารถทำได้โดยอัตโนมัติด้วยโปรแกรมที่อ่านข้อกำหนดของเอกสารของคุณ
เมื่อคุณสร้าง regexp ของคุณแล้วคุณสามารถเรียกใช้บนสตรีมอินพุทของคุณเพื่อเริ่มต้นอย่างรวดเร็วจนถึงจุดเริ่มต้นของเอกสารแรกของคุณ (หรือถัดไป) ดังนี้:
ผมถือว่า:
- docstart
เป็น regex ที่ตรงกับจุดเริ่มต้นของเอกสารทั้งหมดที่
- 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)
โปรดทราบว่าจำเป็นต้องลบอักขระตัวแรกเพื่อให้การค้นหาถัดไปจะไม่พบการจับคู่แบบเดียวกันอีก
แน่นอนว่าการย่อของสตรีมเป็นรูปภาพ อาจเป็นเพียงดัชนีในสตรีม
หมายเหตุสุดท้ายคือ regex ของคุณไม่จำเป็นต้องแม่นยำเกินไปตราบใดที่มันรับรู้จุดเริ่มต้นทั้งหมด ถ้ารู้จักสายอักขระที่ไม่สามารถเป็นจุดเริ่มต้นของเอกสารได้ในบางครั้ง (ค่าบวกเท็จ) ค่าปรับเพียงอย่างเดียวคือค่าใช้จ่ายของการเรียก parser ที่ไร้ประโยชน์
ดังนั้นอาจช่วยให้ regex ง่ายขึ้นหากมีประโยชน์
เกี่ยวกับความเป็นไปได้ของการแก้ปัญหาที่รวดเร็วขึ้น
วิธีแก้ปัญหาข้างต้นควรใช้งานได้ดีในกรณีส่วนใหญ่ อย่างไรก็ตามหากคุณมีไฟล์ขยะและเทราไบต์จำนวนมากในการประมวลผลอาจมีอัลกอริทึมอื่นที่ทำงานเร็วกว่า
ความคิดที่มาจากวิธีการค้นหาสตริงบอยเยอร์มัวร์ อัลกอริทึมนี้สามารถค้นหาสตรีมสำหรับสตริงเดี่ยวอย่างรวดเร็วที่สุดเพราะใช้การวิเคราะห์โครงสร้างของสตริงเพื่อข้ามการอ่านสตรีมส่วนใหญ่กระโดดข้ามเศษเล็กเศษน้อยโดยไม่ต้องมองแม้แต่พวกเขา มันเป็นอัลกอริทึมการค้นหาที่เร็วที่สุดสำหรับสตริงเดียว
ปัญหาที่ยากคือการปรับตัวเพื่อค้นหา regex แทนที่จะเป็นสายเดียวดูเหมือนว่าละเอียดอ่อนมากและอาจไม่ทำงานขึ้นอยู่กับคุณสมบัติของ regex ที่คุณกำลังพิจารณา ซึ่งอาจขึ้นอยู่กับไวยากรณ์ของเอกสารที่คุณกำลังวิเคราะห์คำ แต่อย่าเชื่อใจฉันมากเกินไปเพราะฉันไม่มีเวลาอ่านเอกสารที่ฉันพบอย่างระมัดระวัง
ฉันทิ้งคุณไว้กับตัวชี้หนึ่งหรือสองตัวที่ฉันพบในเว็บรวมถึงตัวชี้วัดที่ชัดเจนว่าเป็นรายงานการวิจัยแต่คุณควรพิจารณาสิ่งนี้ว่าเป็นการเก็งกำไรมากขึ้นอาจเป็นงานวิจัยเพื่อพิจารณาเฉพาะเมื่อคุณประสบปัญหาประสิทธิภาพการทำงานที่รุนแรง และอาจไม่มีโปรแกรมชั้นวางที่จะทำ