|
3 | 3 | '''ตัวตัดคำภาษาไทยโดยใช้หลักการ maximal matching และ TCC |
4 | 4 | พัฒนาโดยคุณ Korakot Chaovavanich |
5 | 5 | Notebook : https://colab.research.google.com/notebook#fileId=1V1Z657_5eSWPo8rLfVRwA0A5E4vkg7SI |
| 6 | +https://colab.research.google.com/drive/14Ibg-ngZXj15RKwjNwoZlOT32fQBOrBx#scrollTo=MYZ7NzAR7Dmw |
6 | 7 | ''' |
7 | 8 | from __future__ import absolute_import, unicode_literals |
8 | 9 | import re |
@@ -82,54 +83,64 @@ def serialize(words_at, p, p2): |
82 | 83 | elif p_ < p2: |
83 | 84 | for path in serialize(words_at, p_, p2): |
84 | 85 | yield [w] + path |
85 | | - |
| 86 | +def bfs_paths_graph(graph, start, goal): |
| 87 | + queue = [(start, [start])] |
| 88 | + while queue: |
| 89 | + (vertex, path) = queue.pop(0) |
| 90 | + for next in graph[vertex]: |
| 91 | + if next == goal: |
| 92 | + yield path + [next] |
| 93 | + else: |
| 94 | + queue.append((next, path+[next])) |
86 | 95 |
|
87 | 96 | def onecut(text, data=['']): |
88 | | - if(data != ['']): |
89 | | - trie = Trie(data) |
90 | | - else: |
91 | | - trie = THAI_WORDS |
92 | | - words_at = defaultdict(list) # main data structure |
93 | | - allow_pos = tcc_pos(text) # ตำแหน่งที่ตัด ต้องตรงกับ tcc |
94 | | - |
95 | | - q = [0] # min-heap queue |
96 | | - last_p = 0 # last position for yield |
97 | | - while q[0] < len(text): |
98 | | - p = heappop(q) |
99 | | - |
100 | | - for w in trie.prefixes(text[p:]): |
101 | | - p_ = p + len(w) |
102 | | - if p_ in allow_pos: # เลือกที่สอดคล้อง tcc |
103 | | - words_at[p].append(w) |
104 | | - if p_ not in q: |
105 | | - heappush(q, p_) |
106 | | - |
107 | | - # กรณี length 1 คือ ไม่กำกวมแล้ว ส่งผลลัพธ์ก่อนนี้คืนได้ |
108 | | - if len(q) == 1: |
109 | | - paths = serialize(words_at, last_p, q[0]) |
110 | | - for w in min(paths, key=len): |
111 | | - yield w |
112 | | - last_p = q[0] |
113 | | - |
114 | | - # กรณี length 0 คือ ไม่มีใน dict |
115 | | - if len(q) == 0: |
116 | | - m = pat_eng.match(text[p:]) |
117 | | - if m: # อังกฤษ, เลข, ว่าง |
118 | | - i = p + m.end() |
119 | | - else: # skip น้อยที่สุด ที่เป็นไปได้ |
120 | | - for i in range(p + 1, len(text)): |
121 | | - if i in allow_pos: # ใช้ tcc ด้วย |
122 | | - ww = trie.prefixes(text[i:]) |
123 | | - m = pat_eng.match(text[i:]) |
124 | | - if ww or m: |
125 | | - break |
126 | | - else: |
127 | | - i = len(text) |
128 | | - w = text[p:i] |
129 | | - words_at[p].append(w) |
130 | | - yield w |
131 | | - last_p = i |
132 | | - heappush(q, i) |
| 97 | + if(data != ['']): |
| 98 | + trie = Trie(data) |
| 99 | + else: |
| 100 | + trie = THAI_WORDS |
| 101 | + graph = defaultdict(list) # main data structure |
| 102 | + allow_pos = tcc_pos(text) # ตำแหน่งที่ตัด ต้องตรงกับ tcc |
| 103 | + |
| 104 | + q = [0] # min-heap queue |
| 105 | + last_p = 0 # last position for yield |
| 106 | + while q[0] < len(text): |
| 107 | + p = heappop(q) |
| 108 | + |
| 109 | + for w in trie.prefixes(text[p:]): |
| 110 | + p_ = p + len(w) |
| 111 | + if p_ in allow_pos: # เลือกที่สอดคล้อง tcc |
| 112 | + graph[p].append(p_) |
| 113 | + if p_ not in q: |
| 114 | + heappush(q, p_) |
| 115 | + |
| 116 | + # กรณี length 1 คือ ไม่กำกวมแล้ว ส่งผลลัพธ์ก่อนนี้คืนได้ |
| 117 | + if len(q)==1: |
| 118 | + pp = next(bfs_paths_graph(graph, last_p, q[0])) |
| 119 | + # เริ่มต้น last_p = pp[0] เอง |
| 120 | + for p in pp[1:]: |
| 121 | + yield text[last_p:p] |
| 122 | + last_p = p |
| 123 | + # สุดท้าย last_p == q[0] เอง |
| 124 | + |
| 125 | + # กรณี length 0 คือ ไม่มีใน dict |
| 126 | + if len(q)==0: |
| 127 | + m = pat_eng.match(text[p:]) |
| 128 | + if m: # อังกฤษ, เลข, ว่าง |
| 129 | + i = p + m.end() |
| 130 | + else: # skip น้อยที่สุด ที่เป็นไปได้ |
| 131 | + for i in range(p+1, len(text)): |
| 132 | + if i in allow_pos: # ใช้ tcc ด้วย |
| 133 | + ww = trie.prefixes(text[i:]) |
| 134 | + m = pat_eng.match(text[i:]) |
| 135 | + if ww or m: |
| 136 | + break |
| 137 | + else: |
| 138 | + i = len(text) |
| 139 | + w = text[p:i] |
| 140 | + graph[p].append(i) |
| 141 | + yield w |
| 142 | + last_p = i |
| 143 | + heappush(q, i) |
133 | 144 |
|
134 | 145 | # ช่วยให้ไม่ต้องพิมพ์ยาวๆ |
135 | 146 |
|
|
0 commit comments