Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики — различия между версиями
Zernov (обсуждение | вклад) (→Алгоритм) |
Zernov (обсуждение | вклад) |
||
Строка 29: | Строка 29: | ||
== Доказательство эквивалентности == | == Доказательство эквивалентности == | ||
− | В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex> | + | В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной. |
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил. | # Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил. | ||
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>. | # Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>. | ||
Строка 38: | Строка 38: | ||
|about=1 | |about=1 | ||
|statement= | |statement= | ||
− | <tex>\forall\,j: 1 \le j \le n</tex> в списке <tex> | + | <tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций. |
|proof= | |proof= | ||
− | Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex> | + | Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций. |
}} | }} | ||
Строка 47: | Строка 47: | ||
|about=2 | |about=2 | ||
|statement= | |statement= | ||
− | Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex> | + | Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>. |
|proof= | |proof= | ||
− | Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex> | + | Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем: |
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>; | * <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>; | ||
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>. | * <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>. | ||
Строка 62: | Строка 62: | ||
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>. | Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>. | ||
|proof= | |proof= | ||
− | Орагнизуем каждый список разбора <tex> | + | Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>. |
− | Время построения <tex> | + | Время построения <tex>D_0</tex> не зависит от входной строки. |
− | Рассмотрим <tex> | + | Рассмотрим <tex>D_j, \, j > 0</tex>. |
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций. | # При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций. | ||
− | # Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex> | + | # Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций. |
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций. | # Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций. | ||
− | Таким образом, на построение списка <tex> | + | Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>. |
}} | }} | ||
Версия 23:33, 4 января 2017
Содержание
Алгоритм
Для начала модифицируем алгоритм Эрли.
Будем рассматривать грамматику без ε-правил и бесполезных символов.
function: // Инициализация useful_loop(0) for j = 1 .. n for = // Первое правило useful_loop(j)
function useful_loop(j):while for // Цикл (*) for = // Второе правило for // Цикл (**) for = // Третье правило =
Доказательство эквивалентности
В циклах, помеченных while
. Данная модификация является корректной.
- Рассмотрим цикл . Если в текущей ситуации этого цикла , то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию в цикле рассматривать не нужно. Если же , то , что возможно, только если . Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как не встречается в правых частях правил.
- Теперь рассмотрим цикл . Так как для каждой ситуации в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для .
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах
и просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.Время работы для однозначной грамматики
Лемма (1): |
в списке находится ситуаций. |
Доказательство: |
Так как грамматика фиксирована, то | количество ситуаций вида не больше некоторой константы. Таким образом, поскольку в находятся ситуации, у которых , всего в будет ситуаций.
Лемма (2): |
Пусть — однозначная КС-грамматика без непорождающих нетерминалов и — цепочка из . Тогда алгоритм Эрли пытается включить в не более одного раза, если . |
Доказательство: |
Ситуацию можно включить в только по правилам (если последний символ — терминал) и (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что включается в , когда рассматриваются две ситуации и (они различны, так как в цикле каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация должна оказаться одновременно в и в . Таким образом, получаем:
Следовательно, |
Теорема: |
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины составляет . |
Доказательство: |
Орагнизуем каждый список разбора таким образом, чтобы по любому символу , можно было за получить список тех и только тех ситуаций, содержащихся в , которые имеют вид .Время построения не зависит от входной строки.Рассмотрим .
|
См. также
Источники информации
- А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.