Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ — различия между версиями
Kabanov (обсуждение | вклад) (→Псевдокод) |
Kabanov (обсуждение | вклад) м (→Алгоритм) |
||
Строка 5: | Строка 5: | ||
== Алгоритм == | == Алгоритм == | ||
− | + | '''Алгоритм Кока-Янгера-Касами''' (''Cocke — Younger — Kasami algorithm'', '''CYK - алгоритм''') - универсальный алгоритм, позволяющий по слову узнать, выводимо ли оно в заданной КС-грамматике в нормальной форме Хомского. | |
− | + | Будем решать задачу [[Динамическое_программирование|динамическим программированием]]. Заведем трехмерный массив d, состоящий из логических значений, и <tex>d[A][i][j] = true</tex> тогда и только тогда, когда из нетерминала <tex>A</tex> правилами грамматики можно вывести подстроку <tex>w[i..j]</tex>. | |
− | <tex> | + | Рассмотрим все пары <tex>\lbrace \langle j, i \rangle | j-i=m \rbrace</tex>, где <tex>m</tex> - константа и <tex>m < n</tex>. |
− | \ | ||
− | |||
− | |||
− | |||
− | </tex>. | ||
− | + | === Шаг 1. База === | |
+ | <tex>m = 0</tex>. В таком случае <tex>i = j</tex>. | ||
− | + | Инициализируем массив для всех нетерминалов, из которых выводится какой-либо символ строки <tex>w</tex>. В таком случае: | |
+ | : <tex>d[A][i][i] = true</tex>, если в грамматике <tex>\Gamma</tex> присутствует правило <tex>A \rightarrow w[i]</tex>. Иначе <tex>d[A][i][i] = false</tex>. | ||
− | + | === Шаг 2. Переход === | |
+ | [[Файл:CYK_rule_2.jpg|thumb|300px]] | ||
− | [[ | + | <tex>m = j - i</tex>. Значения для всех нетерминалов и пар <tex>\lbrace \langle j', i' \rangle | j' - i' < m \rbrace</tex> уже вычислены, поэтому <tex>d[A][i][j] = \bigvee\limits_{A \rightarrow BC}\bigvee\limits_{k = i}^{j-1} d[B][i][k] \wedge d[C][k+1][j]</tex>. То есть, подстроку <tex>w[i \dots j]</tex> можно вывести из нетерминала <tex>A</tex>, если существует продукция вида <tex>A \rightarrow BC</tex> и такое <tex>k</tex>, что подстрока <tex>w[i \dots k]</tex> выводима из <tex>B</tex>, а подстрока <tex>w[k + 1 \dots j]</tex> - из <tex>C</tex>. |
− | + | ||
+ | |||
+ | === Завершение === | ||
+ | После окончания работы ответ содержится в ячейке <tex>a_{S, 1, n}</tex>, где <tex>n = |w|</tex>. | ||
+ | Значение <tex>d[S,1,n]</tex> содержит ответ на вопрос, выводима ли данная строка в данной грамматике. | ||
+ | |||
+ | == Модификации == | ||
+ | Заметим, что если массив будет хранить целые числа, а формулу заменить на <tex>d[A][i][j] = \sum\limits_{A \rightarrow BC}\sum\limits_{k = i}^{j-1} d[B,i,k] \cdot d[C,k+1,j]</tex>, то <tex>d[A,i,j]</tex> - количество способов получить подстроку <tex>w[i \dots j]</tex> из нетерминала <tex>A</tex>. | ||
+ | |||
+ | Пусть <tex>P_{A \rightarrow BC}</tex> - ''стоимость'' вывода по правилу <tex>A \rightarrow BC</tex>. Тогда, если использовать формулу <tex>d[A,i,j] = \min\limits_{A \rightarrow BC} \min\limits_{k = i}^{j-1} ( d[B,i,k] + d[C,k+1,j] + P_{A \rightarrow BC} )</tex>, то <tex>d[A,i,j]</tex> - минимальная стоимость вывода подстроки <tex>a_i...a_j</tex> из нетерминала <tex>A</tex>. | ||
+ | |||
+ | Таким образом, задача о выводе в КС-грамматике в нормальной форме Хомского является обобщением задачи динамического программирования на подотрезке. | ||
== Псевдокод == | == Псевдокод == |
Версия 23:11, 4 ноября 2014
Задача: |
Пусть дана контекстно-свободная грамматика грамматика в нормальной форме Хомского и слово . Требуется выяснить, выводится ли это слово в данной грамматике. |
Содержание
Алгоритм
Алгоритм Кока-Янгера-Касами (Cocke — Younger — Kasami algorithm, CYK - алгоритм) - универсальный алгоритм, позволяющий по слову узнать, выводимо ли оно в заданной КС-грамматике в нормальной форме Хомского. Будем решать задачу динамическим программированием. Заведем трехмерный массив d, состоящий из логических значений, и тогда и только тогда, когда из нетерминала правилами грамматики можно вывести подстроку .
Рассмотрим все пары
, где - константа и .Шаг 1. База
. В таком случае .
Инициализируем массив для всех нетерминалов, из которых выводится какой-либо символ строки
. В таком случае:- , если в грамматике присутствует правило . Иначе .
Шаг 2. Переход
. Значения для всех нетерминалов и пар уже вычислены, поэтому . То есть, подстроку можно вывести из нетерминала , если существует продукция вида и такое , что подстрока выводима из , а подстрока - из .
Завершение
После окончания работы ответ содержится в ячейке
, где . Значение содержит ответ на вопрос, выводима ли данная строка в данной грамматике.Модификации
Заметим, что если массив будет хранить целые числа, а формулу заменить на
, то - количество способов получить подстроку из нетерминала .Пусть
- стоимость вывода по правилу . Тогда, если использовать формулу , то - минимальная стоимость вывода подстроки из нетерминала .Таким образом, задача о выводе в КС-грамматике в нормальной форме Хомского является обобщением задачи динамического программирования на подотрезке.
Псевдокод
boolean CYK(char[] w, list, int S) int n = length(w) boolean d[ ][n][n] for i = 1 ... n for (A w[i] ) d[A,i,i] = true for len = 1 .. n - 1 for i = 1 .. n - len for (A BC ) for k = i .. i + len - 1 d[A][i][i + len] = d[A][i][i + len] or d[B][i][k] and d[C][k + 1][i + len] return d[S][1][n]
Асимптотика
Необходимо вычислить
булевых величин. На каждую требуется затратить операций, где – количество правил. Суммируя по всем правилам получаем конечную сложность .Алгоритму требуется
памяти, где — количество нетерминалов грамматики.Пусть,
- длина входной строки, а - количество правил вывода в грамматике.Обработка правил вида
выполняется за .Проход по всем подстрокам выполняется за
. В обработке подстроки присутствует цикл по всем правилам вывода и по всем разбиениям на две подстроки, следовательно обработка работает за . В итоге - .Следовательно, общее время работы алгоритма -
. Кроме того, алгоритму требуется память (на массив ) объемом .Недостаток алгоритма заключается в том, что изначально грамматику необходимо привести к НФХ.