new chapter

This commit is contained in:
2026-08-25 05:45:43 +03:00
parent 548159e5ea
commit f86537626a
+36 -1
View File
@@ -184,7 +184,42 @@ B=\sum_{i=1}^{n}\ell_i
\end{center}
\end{table}
После сортировки получается массив $(255,280,460,711,758)$, а после вычисления разностей --- $(255,25,180,251,47)$. Для $n=5$ формула даёт $m=7$; полученный 43-битный поток преобразуется в payload \texttt{ZvpACXZy}. Параметрам $b=10$ и $m=7$ соответствуют заголовочные символы \texttt{d} и \texttt{a}, поэтому итоговая строка равна \texttt{set:daZvpACXZy}. Пример показывает, что строка содержит достаточно данных для восстановления упорядоченного множества усечённых хешей, но не исходных имён символов.
После сортировки получается массив $(255,280,460,711,758)$, а после вычисления разностей --- $(255,25,180,251,47)$. Для $n=5$ формула даёт $m=7$; полученный 43-битный поток преобразуется в payload \texttt{ZvpACXZy}. Параметрам $b=10$ и $m=7$ соответствуют заголовочные символы \texttt{d} и \texttt{a}, поэтому итоговая строка равна \texttt{set:daZvpACXZy}.
\section{Построение \texttt{set:}-строк в \texttt{set.c}}
\label{CONSTRUCTION}
Благодаря сценариям автозависимостей \texttt{rpm-build} утилита \texttt{mkset} получает символы из ELF-файлов и далее импользует \texttt{lib/set.c}, вызывая интерфейс построения множества:
\[
\texttt{set\_new()}\ \longrightarrow\
\texttt{set\_add()}\ \longrightarrow\
\texttt{set\_fini()}.
\]
Функция \texttt{set\_new()} создаёт пустую структуру \texttt{struct set}. В исходной реализации она представляет собой растущий массив пар «указатель на строку --- хеш». Функция \texttt{set\_add()} увеличивает ёмкость массива блоками по 1024 элемента и копирует каждое имя отдельным вызовом \texttt{xstrdup()}. На этом этапе хеши ещё не вычисляются, поэтому один объект можно финализировать с заданным значением \texttt{bpp}.
Основную работу выполняет \texttt{set\_fini()}. Её действия следуют в фиксированном порядке:
\begin{enumerate}
\item проверяется непустота множества и условие $10\leq b\leq32$;
\item для каждого имени вычисляется Jenkins OAAT и применяется маска из $b$ младших бит;
\item массив пар сортируется стандартной функцией \texttt{qsort()} по хеш-значению;
\item для равных хешей различных имён выводится предупреждение о коллизии;
\item хеши копируются в числовой массив, а повторяющиеся значения удаляются;
\item массив кодируется последовательно как дельты, код Голомба--Райса и Base62;
\item сформированная строка копируется в динамическую память и возвращается вызывающей стороне.
\end{enumerate}
Удаление повторов необходимо в двух случаях. Во-первых, одно имя может несколько раз попасть во входной поток. Во-вторых, различные имена могут совпасть после усечения хеша. Для семантики $H_b(S)$ оба случая означают один элемент множества. При этом предупреждение о коллизии формируется до удаления повторов, пока реализации ещё доступны исходные строки и можно различить совпадение имён от совпадения их хешей.
Оценим вычислительную сложность. Пусть $L$ --- суммарная длина всех входных имён, $n$ --- их количество, а $B$ --- длина потока Голомба--Райса в битах. Хеширование требует $O(L)$ операций, сортировка --- $O(n\log n)$ сравнений, линейные проходы сортированного массива --- $O(n)$, кодирование --- $O(B)$. Поэтому для исходного варианта
\[
T_{\mathrm{build}}=O(L)+O(n\log n)+O(B).
\]
Хранимые копии строк, массив пар, массив уникальных хешей, битовый буфер и результирующая строка дают дополнительную память порядка
\[
M_{\mathrm{build}}=O(L+n+B).
\]
Главным асимптотическим слагаемым для больших наборов остаётся \texttt{qsort()}, тогда как большое число отдельных копирований строк и наличие промежуточного битового массива влияют на постоянные затраты. Это определяет два независимых направления дальнейшего улучшения: замена сортировки для крупных множеств и потоковое кодирование без промежуточных представлений. При этом любые изменения должны сохранять байтовую совместимость формата.
\References
\begin{enumerate}