К оглавлению

Стеммер Портера

С.И.Хашин

Стемминг (лемматизация) — это процесс нахождения лексической основы для заданного исходного слова. Наиболее известный алгоритм стемминга — это Стеммер Портера:
    абажур           =>    абажур
    абажурный        =>    абажурн
    аббатиса         =>    аббатис
    аббатский        =>    аббатск
    аббатство        =>    аббатств
    аббревиатура     =>    аббревиа
    аббревиатурный   =>    аббревиа
    аббревиация      =>    аббревиа

Алгоритм достаточно известен и подробно описан:
snowball.tartarus.org
www.algorithmist.ru
www.solarix.ru/for_developers

Несмотря на это, найти готовый к использованию алгоритм, не связанный ни с какими библиотеками, не так просто. Поэтому реализацию алгоритма Портера помещаем сюда.

porter.h - заголовочный файл
porter.cpp - реализация.

Алгоритм реализован в модуле porter.h(cpp), который содержит одну-единственную внешнюю функцию:

void StemmPorter(char *s0); // Лемматизация  Портера "на месте" (одно слово)

Предполагается, что строка s состоит ТОЛЬКО из маленьких русских букв (включая ё) в кодировке cp-1251 (стандартная кодировка Windows).
Точнее, считаем, что строка начинается с символа s0[0], первый же встретившийся символ, отличный от

    "абвгдежзийклмнопрстуфхцчшщъыьэюяё";    // полный список из 33-х букв
считается концом строки. Пробелов, точек, символов '\n', и т.п. тоже быть не должно.

Лемматизация производится "на месте", то есть в найденное место строки-аргумента s0 записывается нулевой символ, признак конца строки.

Если исходная строка короче трёх символов, то возвращается исходная строка.

Подробности реализации

Алгоритм хорошо известен, подробно описан, например, в Википедии Стеммер Портера. Доступны несколько версий алгоритма на С++. Однако в них имеются некоторые разночтения. Поэтому приведем детали именно той версии, которая реализована здесь.

Сначала введем некоторые определения:

Пример

В слове «противоестественном»:

Теперь определим несколько классов окончаний слова. Я оставлю их оригинальные названия из исходного описания алгоритма.

PERFECTIVE GERUND
Группа 1: в, вши, вшись.
Группа 2: ив, ивши, ившись, ыв, ывши, ывшись.

Окончаниям из группы 1 должна предшествовать буква а или я.

ADJECTIVE

ее, ие, ые, ое, ими, ыми, ей, ий, ый, ой, ем, им, ым, ом, его, ого, ему, ому, их, ых, ую, юю, ая, яя, ою, ею.

PARTICIPLE
Группа 1: ем, нн, вш, ющ, щ.
Группа 2: ивш, ывш, ующ.

Окончаниям из группы 1 должна предшествовать буква а или я.

REFLEXIVE
ся, сь.
VERB
Группа 1: ла, на, ете, йте, ли, й, л, ем, н, ло, но, ет, ют, ны, ть, ешь, нно.
Группа 2: ила, ыла, ена, ейте, уйте, ите, или, ыли, ей, уй, ил, ыл, им, ым, ен,
ило, ыло, ено, ят, ует, уют, ит, ыт, ены, ить, ыть, ишь, ую, ю.

Окончаниям из группы 1 должна предшествовать буква а или я.

NOUN
а, ев, ов, ие, ье, е, иями, ями, ами, еи, ии, и, ией, ей, ой, ий, й, иям, ям,
ием, ем, ам, ом, о, у, ах, иях, ях, ы, ь, ию, ью, ю, ия, ья, я.

SUPERLATIVE:

ейш, ейше.

DERIVATIONAL

ост, ость.

ADJECTIVAL

ADJECTIVAL определяется как ADJECTIVE или PARTICIPLE + ADJECTIVE. Например: бегавшая = бега + вш + ая.

Правила

При поиске окончания из всех возможных выбирается наиболее длинное. Например, в слове величие выбираем окончание ие, а не е.

Все проверки производятся над областью RV. Так, при проверке на PERFECTIVE GERUND предшествующие буквы а и я также должны быть внутри RV. Буквы перед RV не участвуют в проверках вообще.

Шаг 1

Найти окончание PERFECTIVE GERUND. Если оно существует – удалить его и завершить этот шаг.

Иначе, удаляем окончание REFLEXIVE (если оно существует). Затем в следующем порядке пробуем удалить окончания: ADJECTIVAL, VERB, NOUN. Как только одно из них найдено – шаг завершается.

Шаг 2

Если слово оканчивается на и – удаляем и.

Шаг 3

Если в R2 найдется окончание DERIVATIONAL – удаляем его.

Шаг 4

Возможен один из трех вариантов:

К оглавлению


free counters