Алгоритм разбивки слов на слоги
Post date: Apr 21, 2010 9:32:14 PM
Недавно столкнулся с проблемой реализации упрощенного алгоритма разбивки слов на слоги. Текущий алгоритм, который используется в Foliant, реализован на основе шаблонов переносов TeX. Пришлось долго повозится, что бы реализовать его средствами J2ME, но потом оказалось, что этот алгоритм использует много памяти. На многих телефонах открытие книги с включенными переносами вызывало серьезную ошибку, связанную с переполнением памяти. Ведь приходилось загружать в память таблицу правил переносов для русского языка, а он довольно таки увесистый, да и скорость работы реализованного алгоритма оставляла желать лучшего.
По-этому я начал искать упрощенные алгоритмы, которые бы были не столь требовательны к памяти. Поиск превел меня к алгоритму П.Христова в модификации Дымченко и Варсанофьева. Он довольно простой и не требовательный к ресурсам, но, как оказалось, использует регулярные выражения. Но и это не остановило меня. Пять минут поиска и вот - регулярные выражения для J2ME.
Реализация не заставила себя ждать и в течении часа уже проводилось тестирование на телефоне. К моему огорчению, реализация RegExp для J2ME была далека от совершенства, она работала довольно медленно даже по сравнению с предыдущей реализацией. Пересмотрев алгоритм, пришла идея его оптимизации. Она заключалась в следующем:
1. Заменить буквы в слове соответствующими "метками"
x=йьъ
g=аеёиоуыэюяaeiouy
s=бвгджзклмнпрстфхцчшщbcdfghjklmnpqrstvwxz
к примеру слово "подъезд" -> "sgsxgss", "habrahabr" -> "sgssgsgss"
2. Задать правила замены, пришлось немного извратиться
"xgg" -> "x-gg"
"xgs" -> "x-gs"
"xsg" -> "x-sg"
"xss" -> "x-ss"
"gssssg" -> "gss-ssg"
"gsssg" -> "gss-sg"
"gsssg" -> "gs-ssg"
"sgsg" -> "sg-sg"
"gssg" -> "gs-sg"
"sggg" -> "sg-gg"
"sggs" -> "sg-gs"
3. Произвести банальную замену в предыдущем слове
"подъезд" -> "sgsxgss" -> "sgsx-gss"
"habrahabr" -> "sgssgsgss" -> "sgs-sg-sgss"
4. Нанести расставленные переносы на изначальное слово
"подъезд" -> "sgsxgss" -> "sgsx-gss" -> "подъ-езд"
"habrahabr" -> "sgssgsgss" -> "sgs-sg-sgss" -> "hab-ra-habr"
В итоге, получил быстрый алгоритм, который использует минимум памяти и работает как с русским, так и английским языком. Качество разбивки слов не всегда удовлетворительное, хотя, по заявлению создателей алгоритма, он точен на 99.99%, в чем я конечно сомневаюсь...
Реализацию алгоритма можно взять здесь Hyphenator.java.