บทความนี้อธิบายถึงอัลกอริทึมการแบ่งส่วนคำสองทิศทางแบบสองทิศทางที่ใช้โดย Java แบ่งปันสำหรับการอ้างอิงของคุณดังนี้:
อัลกอริทึมการแบ่งส่วนคำที่เป็นที่นิยมหลายวิธีคือ: วิธีการแบ่งส่วนคำตามการจับคู่สตริงวิธีการแบ่งส่วนคำตามวิธีการทำความเข้าใจและวิธีการแบ่งส่วนคำตามสถิติ บทความนี้ใช้วิธีการจับคู่สตริง
ส่งต่อการจับคู่สูงสุดของการจับคู่:
อัลกอริทึมนี้ดำเนินการตามพจนานุกรมคำนามคำซึ่งทำการจับคู่การแบ่งส่วนจากด้านซ้ายของสตริง หากพจนานุกรมมีอยู่มันจะส่งคืนคำที่แบ่งออกและตัดคำจากสตริงก่อนหน้าและลูปเพื่อตัดจนกว่าขนาดสตริงคือ 0
ตัวอย่างเช่น: str = "เราทุกคนเป็นนักเรียนจากคณะวิศวกรรมสารสนเทศ, มหาวิทยาลัย Northwest A&F มหาวิทยาลัย", (สมมติว่าเรากำหนดความยาวสูงสุดของการตัดสูงสุด = 8 นั่นคือแปดตัวละครจีน)
1. กำหนดคำว่าความยาวของคำนาม len = สูงสุด, นำอักขระ len ออกจากคำซ้าย = "เราทุกคนคือการเกษตรและป่าไม้ตะวันตกเฉียงเหนือ" และจับคู่คำในพจนานุกรม;
2. หากไม่มีคำดังกล่าวในพจนานุกรมให้ลบอักขระสุดท้ายและกำหนดให้เป็นคำและค่า LEN จะลดลง 1;
3. ทำซ้ำขั้นตอนที่ 2 จนกว่าจะพบคำในพจนานุกรมหรือเลน = 1 ออกจากลูป;
4. ตัดคำที่แบ่งออกจาก STR และทำซ้ำขั้นตอนที่ 1, 2 และ 3 จนกระทั่ง STR ถูกย่อยสลาย
ย้อนกลับการจับคู่คำกริยาที่ตรงกัน:
เช่นเดียวกับอัลกอริทึมการแบ่งส่วนคำไปข้างหน้ามันเริ่มต้นจากด้านขวาของสตริงจนกว่าความยาวของสตริงคือ 0 ฉันจะไม่เข้าไปในรายละเอียดที่นี่
การจับคู่สองทาง:
วิธีนี้คือการสร้างความคลุมเครือในการแบ่งกลุ่มความกำกวมบนพื้นฐานของการส่งต่อคำกริยาและการย้อนกลับ เสนอการใช้งาน "อัลกอริทึมการกินงู" สตริงเพื่อทำการแบ่งส่วนคำคืออาหาร มีงูตะกละ 2 ตัวหนึ่งกินจากซ้ายไปขวา อีกคนกินจากขวาไปซ้าย ตราบใดที่ผลการเรียนรู้ทางซ้ายและขวามีความคลุมเครืองูทั้งสองจะกัดมัน สายที่งูกินกลายเป็นคำกริยา หากมีความคลุมเครือระหว่างผู้มีส่วนร่วมด้านซ้ายและขวางูทั้งสองจะกินต่อไป เมื่องูสองตัวกินจุดตัดระหว่างสายจะไม่มีความกำกวมอย่างแน่นอน ในเวลานี้คำกริยาในท้องงูโลภทางด้านซ้ายไม่มีความคลุมเครืออยู่ตรงกลางและคำกริยาในท้องงูโลภทางด้านขวาซึ่งสามเป็นคำกริยาสุดท้าย
บทความนี้คือการแบ่งย่อหน้าทั้งหมดออกเป็นคำ ขั้นแรกย่อหน้าจะถูกแบ่งออกเป็นประโยคตามเครื่องหมายวรรคตอนจากนั้นแต่ละประโยคจะถูกส่งออกเพื่อแบ่งคำ
แพ็คเกจ cn.nwsuaf.spilt; นำเข้า java.io.bufferedreader; นำเข้า java.io.filereader; นำเข้า java.io.ioexception; นำเข้า java.util.arraylist; นำเข้า java.util.hashmap; อัลกอริทึมการแบ่งส่วนคำศัพท์สูงสุดแบบสองทิศทางไปข้างหน้า / *** ความยาวการตัดคำสูงสุดคือห้าอักขระภาษาจีน*/ ส่วนตัว int max_length = 5; /** * อ่านพจนานุกรมคำนามในวิธีการก่อสร้างและเก็บไว้ในแผนที่ * * @throws ioexception */public wordspilt () พ่น IOException {bufferedreader br = bufferedreader ใหม่ (ใหม่ filereader ("src/dict.txt")); สตริงบรรทัด = null; ในขณะที่ ((line = br.readline ())! = null) {line = line.trim (); map.put (บรรทัด, 0); } br.close (); } / *** ตั้งค่าความยาวการตัดคำสูงสุด** @param max* ความยาวการตัดคำสูงสุด* / โมฆะสาธารณะ setMaxLength (int max) {this.max_length = สูงสุด; } / ** * รับความยาวการตัดคำสูงสุดปัจจุบันค่าเริ่มต้นคือ 5 (5 อักขระภาษาจีน) * * @return ความยาวคำสูงสุดของคำสูงสุด * / สาธารณะ int getMaxLength () {return this.max_length; } / ** * อัลกอริทึมการตัดคำสูงสุดการจับคู่ * * @param spiltstr * สตริงที่จะแยก * @param lefttoright * ทิศทางการหั่น, จริงมาจากซ้ายไปขวา, เท็จคือสตริงที่หารจากขวาไปซ้าย * @return * / รายการสาธารณะ คืนค่า null; // จัดเก็บรายการสตริงแยกการจับคู่บวก <String> leftwords = new ArrayList <String> (); // จัดเก็บรายการสตริงแยกที่ตรงกันเชิงลบ <String> rightWords = new ArrayList <String> (); // string สำหรับการหั่นสตริงคำ = null; // ใช้ความยาวของคำเริ่มต้นเป็นค่าสูงสุด int wordlength = max_length; // อยู่ในตำแหน่งปัจจุบันของตำแหน่งสตริง int = 0; // ความยาวของสตริงได้รับการประมวลผลความยาว int = 0; // ลบช่องว่างพิเศษในสตริง spiltstr = spiltstr.trim (). replaceall ("// s+", ""); // เมื่อสตริงที่จะหั่นเป็นชิ้นไม่หั่นบางส่วนการแบ่งส่วนลูปในขณะที่ (ความยาว <spiltstr.length ()) {// ถ้าความยาวของสตริงที่ไม่ได้หั่นเป็นชิ้นเล็กกว่าค่าสูงสุดให้ความยาวของคำเท่ากับความยาวของคำว่า // มิฉะนั้นให้ใช้ค่าเริ่มต้นอื่น wordLength = max_length; // หากเป็นการจับคู่สูงสุดไปข้างหน้าให้เริ่มตัดจากตำแหน่งของ spiltstr ถ้า (leftToright) {ตำแหน่ง = ความยาว; word = spiltstr.substring (ตำแหน่ง, ตำแหน่ง + wordlength); } // หากเป็นการจับคู่ค่าเท่ากันสูงสุดให้เริ่มตัดจากจุดสิ้นสุดของ spiltstr else {position = spiltstr.length () - ความยาว; word = spiltstr.substring (ตำแหน่ง - wordlength, ตำแหน่ง); } // เริ่มตัดสตริงของความยาวที่ระบุจากตำแหน่งปัจจุบัน // word = spiltstr.substring (ตำแหน่ง, ตำแหน่ง + wordLength); // หากไม่มีการตัดสตริงในพจนานุกรมคำนามให้ทิ้งตัวละครในขณะที่ (! map.containskey (คำ)) {// ถ้ามันเป็นคำเดียวให้ออกจากลูปถ้า (word.length () == 1) {// ถ้าเป็นตัวอักษรหรือจำนวน วนลูปโดยตรงเพื่อเพิ่มอักขระต่อเนื่องที่ตามมาถ้า (lefttoright) {สำหรับ (int i = spiltstr.indexof (ตำแหน่ง, ตำแหน่ง)+1; i <spiltstr .length (); i ++) {ถ้า (spiltstr.charat (i)> = '0' && spiltstr.charat spiltstr. Charat (i) <= 'z') || (spiltstr.charat (i)> = 'a' && spiltstr. Charat (i) <= 'z')) {word += spiltstr.charat (i); } else break; }} else {// ถ้าเป็นการจับคู่ย้อนกลับเพิ่มและพลิกตัวเลขต่อเนื่องและตัวอักษรตัวอักษรก่อนตำแหน่งปัจจุบันสำหรับ (int i = spiltstr.indexof (คำ, ตำแหน่ง - 1) - 1; i> = 0; i--) {ถ้า (spiltstr.charat (i)> = '0' (spiltstr.charat (i)> = 'a' && spiltstr.charat (i) <= 'z') || if (i == 0) {StringBuffer SB = ใหม่ StringBuffer (Word); word = sb.reverse (). toString (); }} else {// flip การทำงาน StringBuffer sb = new StringBuffer (Word); word = sb.reverse (). toString (); หยุดพัก; } } } } หยุดพัก; } // หากเป็นการจับคู่สูงสุดไปข้างหน้าให้ทิ้งอักขระตัวสุดท้ายถ้า (ซ้าย) word = word.substring (0, word.length () - 1); // มิฉะนั้นจะทิ้งอักขระตัวแรกคำอื่น = word.substring (1); } // บันทึกสตริงแยกไปยังตารางที่ระบุถ้า (ซ้าย) leftwords.add (Word); else rightwords.add (word); // สตริงที่ประมวลผลเพิ่มความยาว += word.length (); } // ถ้ามันเป็นการจับคู่สูงสุดผกผันให้ปรับสตริงในตารางเพื่อส่งต่อถ้า (! leftToright) {สำหรับ (int i = rightwords.size ()-1; i> = 0; i--) {leftwords.add (rightwords.get (i)); }} // ส่งคืนผลการหั่นกลับไปทางซ้าย; } / ** * พิจารณาว่าทั้งสองชุดมีค่าเท่ากัน * * @param list1 * ตั้งค่า 1 * @param list2 * ตั้ง 2 * @return return true ถ้าเท่ากันหรือเท็จ * / public boolean isequal (รายการ <String> list1, รายการ <String> list2) if (list1.size ()! = list2.size ()) ส่งคืนเท็จ; สำหรับ (int i = 0; i <list1.size (); i ++) {ถ้า (! list1.get (i) .equals (list2.get (i))) ส่งคืนเท็จ; } return true; } / *** ฟังก์ชั่นความคลุมเครือของอนุภาค discriminant** @param inputstr* สตริงที่จะถูกแบ่ง* @return พาร์ติชันผลลัพธ์* / รายการสาธารณะ <String> RESUCTIONWARD (String InputStr) {// รายการผลลัพธ์พาร์ติชัน <String> ผลลัพธ์ = new ArrayList <String> (); // "งูซ้าย" รายการผลลัพธ์ <String> resultLeft = new ArrayList <String> (); // "งูขนาดกลาง" (ส่วนที่แตกต่าง) รายการผลประกอบการ <String> resultMiddle = new ArrayList <String> (); // "งูขวา" รายการผลประกอบการ <String> resultright = new ArrayList <String> (); // ไปข้างหน้ารายการผลลัพธ์การแบ่งส่วนคำที่ตรงกันสูงสุด <String> left = new ArrayList <String> (); // รายการผลการแบ่งส่วนคำที่ตรงกันสูงสุดของคำว่า <String> ขวา = new ArrayList <String> (); ซ้าย = หก (inputstr, true); /*system.out.println(" forward ผลการเรียน: "); สำหรับ (สตริงสตริง: ซ้าย) {system.out.print (สตริง + "/"); } system.out.println ("/n ผลการแทรกผกผัน:"); */ right = spilled (inputstr, false); /*สำหรับ (สตริงสตริง: ขวา) {system.out.print (สตริง + "/"); } system.out.println ("/ nboth-way คำศัพท์คำศัพท์:");*/ // // พิจารณาว่าคำที่มีการประกบกันของคำที่ปลายทั้งสองนั้นมีการตัดกันตรงกลางของสตริงอินพุตหรือไม่ ตราบใดที่ไม่มีทางแยกมันจะวนรอบในขณะที่ (ซ้าย get (0) .length () + ขวา get (ขวา size () - 1) .length () <inputstr .length ()) {// ถ้าผลลัพธ์ของคำพูดไปข้างหน้า หยุดพัก; } // หากผลลัพธ์ของคำที่เป็นคำไปข้างหน้าและย้อนกลับมีความแตกต่างกันดังนั้นอันที่มีจำนวนน้อยกว่าจะถูกนำมาใช้และไม่จำเป็นต้องวนรอบถ้า (ซ้าย size ()! = ขวา size ()) {resultmiddle = ซ้าย ซ้าย: ขวา; หยุดพัก; } // หากไม่ตรงตามเงื่อนไขข้างต้นให้ใช้อัลกอริทึม "งู" // let "งูโลภ" กินคำแรกของคำศัพท์คำศัพท์ที่เป็นผลมา // ปล่อยให้ "งูโลภขวา" กินคำสุดท้ายของคำที่ย้อนกลับผลลัพธ์ resultright.add (right.get (right.size () - 1)); // ลบคำที่กินโดย "งู" inputStr = inputstr.substring (ซ้าย get (0) .length ()); inputStr = inputstr.substring (0, inputstr.length () - right.get (right.size () - 1) .length ()); // ทำความสะอาดผลลัพธ์การแบ่งส่วนคำบวกและคำย้อนกลับก่อนหน้านี้เพื่อป้องกันการรบกวนซ้าย clear (); ขวา. clear (); // เริ่มต้นคำกริยาสำหรับ uneating strings left = spilled (inputstr, true); ขวา = หก (inputstr, false); } // จุดสิ้นสุดของลูปหมายความว่าทั้งสองไม่คลุมเครือหรือ "งูโลภ" กินจากปลายทั้งสองไปยังทางแยก // ถ้ามันเป็นคำว่าคำกริยาที่จุดตัดการตัดสินต่อไปนี้จะต้องทำ: // (left.get (0) .length () + right.get (right.size () - 1) .length ()> inputstr .length ()) resultmiddle = ซ้าย; // ถ้าจุดตัดกลางเพิ่งเสร็จสิ้นจะไม่มีการทับซ้อนกัน: // อนุภาคแรกในทิศทางไปข้างหน้า + ความยาวของอนุภาคสุดท้ายในทิศทางย้อนกลับ = ป้อนความยาวรวมของสตริงจากนั้นทิศทางไปข้างหน้าและทิศทางย้อนกลับสามารถสะกดได้ถ้า (ซ้าย (0). resultmiddle.add (ซ้าย get (0)); resultmiddle.add (right.get (right.size () - 1)); } // เพิ่มผลลัพธ์คำนามที่ไม่ชัดเจนในผลลัพธ์สุดท้ายสำหรับ (สตริงสตริง: resultleft) {result.add (สตริง); } สำหรับ (สตริงสตริง: resultmiddle) {result.add (สตริง); } // อนุภาคที่เก็บไว้ใน "งูโลภขวา" ควรปรับให้เป็นไปข้างหน้าสำหรับ (int i = resultright.size ()-1; i> = 0; i--) {result.add (resultright.get (i)); } ผลตอบแทนผลลัพธ์; } / ** * แบ่งย่อหน้าออกเป็นหลายประโยคและทำการแบ่งส่วนคำแยกกัน * * @param inputstr * ย่อหน้าที่จะถูกแบ่ง * @return ผลการเรียนรู้ของวรรคนี้ * / รายการสาธารณะ <String> ResultsPilt // หากพบเครื่องหมายวรรคตอนมันจะถูกแบ่งออกเป็นหลายประโยคสตริง regex = "[,.;!?]"; สตริง [] st = inputstr.split (regex); // เพิ่มผลการอนุรักษ์ของแต่ละประโยคไปยังผลลัพธ์คำนามสุดท้ายสำหรับ (String stri: st) {list <string> list = resultword (stri); result.addall (รายการ); } ผลตอบแทนผลลัพธ์; } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// ตัวอย่าง: มาดูว่าราคาบ้านมีราคาแพงหรือไม่? เทเบิลเทนนิสสแกนเนอร์อินพุต = สแกนเนอร์ใหม่ (System.in); string str = input.nextline (); WordsPilt wordsPilt = null; ลอง {wordspilt = new wordspilt (); } catch (ioexception e) {e.printstacktrace (); } รายการ <string> list = wordspilt.resultword (str); สำหรับ (สตริงสตริง: รายการ) {system.out.print (สตริง + "/"); -src/dict.txt เป็นไฟล์พจนานุกรมและการตั้งค่ามีดังนี้:
ยินดีต้อนรับสู่ Wulin.com Script Download Script Tutorial Material
ผลการดำเนินการมีดังนี้:
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับอัลกอริทึม Java ผู้อ่านที่มีความสนใจในเว็บไซต์นี้สามารถดูหัวข้อ: "โครงสร้างข้อมูล Java และการสอนอัลกอริทึม", "บทสรุปของเคล็ดลับการดำเนินงาน Java Dom", "บทสรุปของไฟล์ Java และเคล็ดลับการดำเนินการไดเรกทอรี" และ "สรุป
ฉันหวังว่าบทความนี้จะเป็นประโยชน์กับการเขียนโปรแกรม Java ของทุกคน