Индексный поиск по регулярным выражениям (Александр...
TRANSCRIPT
![Page 1: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/1.jpg)
Индексный поиск по регулярным выражениям
Александр Коротков
![Page 2: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/2.jpg)
Введение
![Page 3: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/3.jpg)
Регулярные выражения
• мощный инструмент обработки текстовой информации
• основаны на математической лингвистике
![Page 4: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/4.jpg)
Автоматы… нет, не слышал
![Page 5: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/5.jpg)
Итак… автоматы
• Регулярное выражение => автомат
• Все так и делают
![Page 6: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/6.jpg)
Итак... автоматы
• Автомат – это граф
• Автомат «читает» строку
![Page 7: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/7.jpg)
Пример
/a(bc)*d/становится
![Page 8: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/8.jpg)
Пример
xyzabcbcdxyz
![Page 9: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/9.jpg)
Пример
xyzabcbcdxyz
![Page 10: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/10.jpg)
Пример
xyzabcbcdxyz
![Page 11: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/11.jpg)
Пример
xyzabcbcdxyz
![Page 12: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/12.jpg)
Пример
xyzabcbcdxyz
![Page 13: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/13.jpg)
Пример
xyzabcbcdxyz
![Page 14: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/14.jpg)
Пример
xyzabcbcdxyz
![Page 15: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/15.jpg)
Пример
xyzabcbcdxyz
![Page 16: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/16.jpg)
Пример
xyzabcbcdxyz
![Page 17: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/17.jpg)
Пример
xyzabcbcdxyz
![Page 18: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/18.jpg)
Пример
xyzabcbcdxyz
![Page 19: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/19.jpg)
Пример
xyzabcbcdxyz
![Page 20: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/20.jpg)
Пример
xyzabcbcdxyzУра! Подходит!
![Page 21: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/21.jpg)
Ну теперь все мы знаем…
![Page 22: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/22.jpg)
Поиск по регекспам в PostgreSQL
• есть :)
• последовательный :(
![Page 23: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/23.jpg)
Инвертированные индексына n-грамах
![Page 24: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/24.jpg)
N-грамы?
![Page 25: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/25.jpg)
N-грамы
• N-грамы – это подстрока длины n
• Широко используются
![Page 26: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/26.jpg)
Инвертированные индексы на n-грамах
• Соответствие n-грама <=> набор id
• Модуль pg_trgm содержит реализацию для n = 3
![Page 27: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/27.jpg)
pg_trgm
' e': {1,2} 'egu': {1,3} 'pre': {1,2}' r': {1,3} 'er ': {3} 'reg': {1,3}' s': {2,3} 'ess': {1,2} 'res': {1,2}' ex': {1,2} 'exp': {1,2} 'sio': {1}' re': {1,3} 'gul': {1,3} 'siv': {2}' sp': {2,3} 'ion': {1} 'spe': {2,3}'ach': {2} 'ive': {2} 'ssi': {1,2}'ake': {3} 'ker': {3} 'ula': {1,3}'ar ': {1,3} 'lar': {1,3} 've ': {2}'ch ': {2} 'ns ': {1} 'xpr': {1,2}'eac': {2} 'ons': {1} 'eak': {3} 'pea': {2,3}
1. "regular expressions",2. "expressive speach",3. "regular speaker"
=>
![Page 28: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/28.jpg)
Частоты N-грам
DBLP: 2.5M заголовков статей
• “the” - 360K• “zzz” – 1
глава "Zzzzzzzzzzzzzzzzzzzzzzzzzz" книги "Formal Specification and Development in Z and B" от David Everett
![Page 29: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/29.jpg)
Не все N-грамы одинаково полезны
![Page 30: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/30.jpg)
V-грамы и мультиграмы
• У n-грамы индивидуальное n
• Выше эффективность!
![Page 31: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/31.jpg)
V-грамы или мультиграмы
Проблемы:• Трудно поддерживать
актуальность• …
![Page 32: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/32.jpg)
Патентный тролли!
![Page 33: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/33.jpg)
Как использовать индексдля поиска по регэкспам?
![Page 34: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/34.jpg)
Общая идея/[ab]cde/ => (acd OR bcd) AND cde
![Page 35: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/35.jpg)
/[ab]cde/ => (acd OR bcd) AND cde
Как?
![Page 36: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/36.jpg)
Существующие подходы к извлечению n-грам
из регулярных выражений
![Page 37: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/37.jpg)
Научная работа
Junghoo Ch and Sridhar Rajagopalan, A fast regular expression indexing engine, Proceedings 18th International Conference on Data Engineering, 2002
Всё ещё широко цитируется, как актуальное решение в данной области.
![Page 38: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/38.jpg)
Метод FREE
• Извлечь дерево непрерывных участков строки из регэкспа.
• Преобразование этих непрервыных кусков в мультиграмы (n-грамы с изменяемым n)
• Использовать инвертированный индекс на мультиграмах для выполнения запроса
![Page 39: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/39.jpg)
Метод FREE: пример
Дерево для /(abcd|efgh)(ijklm|x*)/
![Page 40: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/40.jpg)
Метод FREE: пример
Заменить узлы “*” на NULL
![Page 41: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/41.jpg)
Метод FREE: пример
NULL “съедает” родительский узел OR
![Page 42: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/42.jpg)
Метод FREE: пример
Узел AND “съедает” дочерний NULL
![Page 43: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/43.jpg)
Метод FREE: пример
Теперь немного упростим
![Page 44: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/44.jpg)
Метод FREE: пример
Разобьем непрерывные куски строк на n-грамы
![Page 45: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/45.jpg)
Google code search
![Page 46: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/46.jpg)
Google code search
• Запустился в 2006.
• Скорее всего что-то получше, чем предыдущий метод.
• Но мы не знаем что... :(
![Page 47: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/47.jpg)
Мы не знали что, пока..
• Google code search закрылся в 2011 :(• http://swtch.com/~rsc/regexp/regex
p4.html• Более 5 лет интриги!
![Page 48: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/48.jpg)
Метод google code search
• 5 характеристик: emptyable, exact, prefix, suffix, match.• Характеристики рекурсивно
объединяются• Инвертированный индекс на
триграммах
![Page 49: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/49.jpg)
Метод google code search
Исходное выражение: /a(bc)+d/a: {exact: a}bc: {exact: bc}d: {exact: d}(bc)+: {prefix:bc, suffix: bc}a(bc)+: {prefix:abc, suffix:bc}a(bc)+d: {prefix:abc, suffix:bcd}
![Page 50: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/50.jpg)
Метод google code search
/a(bc)+d/
{prefix:abc, suffix:bcd}
abc AND bcd
![Page 51: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/51.jpg)
Предлагаемый метод
![Page 52: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/52.jpg)
Предлагаемый метод
• Автомат => граф на триграмах• Упростить• Использовать GIN индекс
pg_trgm
![Page 53: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/53.jpg)
Пример преобразования
/a(b+|c+)d/
![Page 54: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/54.jpg)
Пример преобразования
![Page 55: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/55.jpg)
Пример преобразования
![Page 56: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/56.jpg)
Пример преобразования
![Page 57: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/57.jpg)
Пример преобразования
![Page 58: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/58.jpg)
Пример преобразования
![Page 59: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/59.jpg)
Пример преобразования
![Page 60: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/60.jpg)
Пример преобразования
![Page 61: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/61.jpg)
Пример преобразования
![Page 62: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/62.jpg)
Пример преобразования
![Page 63: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/63.jpg)
Пример преобразования
![Page 64: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/64.jpg)
Пример преобразования
![Page 65: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/65.jpg)
Пример преобразования
![Page 66: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/66.jpg)
Пример преобразования
![Page 67: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/67.jpg)
Пример преобразования
![Page 68: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/68.jpg)
Пример преобразования
![Page 69: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/69.jpg)
Пример преобразования
![Page 70: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/70.jpg)
Пример преобразования
![Page 71: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/71.jpg)
Пример преобразования
Результат можно упростить
![Page 72: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/72.jpg)
Упрощение
abd abb bbd acd acc ccd
1 0 0 0 0 0
0 1 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 1
abd OR(abb AND bbd) ORacd OR(acc AND ccd)
![Page 73: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/73.jpg)
Сравнение на примерах
Regex: /(abc|cba)def/FREE: (abc OR cba) AND def GSC: def AND ((abc AND bcd AND cde) OR (ade AND bad AND cba))Предложенный метод:(abc AND bcd AND cde AND def) OR (ade AND bad AND cba AND def)
![Page 74: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/74.jpg)
Сравнение на примерах
Regex: /abc+de/FREE: nothing GSC: abc AND cdeПредложенный метод :(abc AND cde AND bcd) OR (abc AND cde AND bcc AND ccd)
![Page 75: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/75.jpg)
Сравнение на примерах
Regex: /(abc*)+de/FREE: nothing GSC: nothingПредложенный метод :(abd AND bde) OR (abc AND bcd AND cde) OR (abc AND bcc AND ccd AND cde)
![Page 76: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/76.jpg)
Сравнение на примерах
Regex: /ab(cd)*ef/FREE: nothing GSC: nothingПредложенный метод : (abe AND bef) OR(abc AND bde AND cde AND def)
![Page 77: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/77.jpg)
Тесты производительности2.5 M заголовков статей DBLP средней длины 47
Regex Index scan Seq scan
/database.*(sql|query)/ 773 ms 18653 ms
/postgres(ql)?/ 268 ms 17574 ms
/plan+er/ 253 ms 12885 ms
/(nucl|anino).*acid/ 200 ms 20085 ms
/[aei](bc)+a/ 2 ms 13195 ms
![Page 78: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/78.jpg)
Патч к pg_trgm в разработке
Патч отправлен в mailing list:http://archives.postgresql.org/pgsql-hackers/2011-11/msg01297.php
![Page 79: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/79.jpg)
Проблемы
• Может получиться большой граф• Может получиться большое
«упрощенное представление» или его долго считать• Использование триграм вместо v-
грам (мультиграм)
![Page 80: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/80.jpg)
Было опущено
• Детерминированные vs недетерминированные автоматы• Группировка символов в цвета• Начало и конец строки
![Page 81: Индексный поиск по регулярным выражениям (Александр Коротков)](https://reader033.vdocuments.mx/reader033/viewer/2022052906/558c946dd8b42af0248b4592/html5/thumbnails/81.jpg)
Спасибо за внимание!