Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Разработка эффективных алгоритмов.doc
Скачиваний:
118
Добавлен:
24.11.2019
Размер:
1.2 Mб
Скачать

5.2.3. Умножение матриц по Штрассену

Алгоритм Штрассена работает с квадратными матрицами. На самом деле он настолько эффективен, что иногда разумно расширить матрицы до квадратных, и при этом он все равно дает выигрыш, превышающий расходы на введение дополнительных элементов.

Для умножения 2х2 матриц алгоритм Штрассена использует семь формул. Эти формулы чрезвычайно неестественны, и, к сожалению, в оригинальной статье Штрассена не объясняется, как он пришел к ним. Замечательно, что как сами формулы, так и их использование не требует, чтобы умножение элементов матрицы было коммутативным. Это означает, в частности, что сами эти элементы могут быть матрицами, а, значит, алгоритм Штрассена можно применять рекурсивно. Вот формулы Штрассена:

x1=(G1,1+G2,2) (H1,1+H2,2)

x2=(G2,1+G2,2) H1,1

x3=G1,1(H1,2-H2,2)

x4=G2,2(H2,1-H1,1)

x5=(G1,1+G2,2) H2,2

x6=(G2,1-G1,1)(H1,1+H1,2)

x7=(G2,1-G2,2)(H2,1+H2,2)

Теперь элементы матрицы R могут вычисляться по формулам

R1,1=x1+x4-x5+x7;

R2,1=x2+x4;

R1,2=x3+x5;

R2,2=x1+x3-x2+x6.

Анализ общего случая показывает, что число умножений при перемножении двух NN матриц приблизительно равно N2.81, а число сложений 6N2.81-6N2.

На практике алгоритм Штрассена применяется редко: его использование требует аккуратного отслеживания рекурсии. Важность его состоит в том, что это первый алгоритм, с помощью которого умножение матриц требует менее, чем О(N3) операций.

Сводная таблица оценок алгоритмов для умножения квадратных матриц размером NN:

Умножений

Сложений

Стандартный алгоритм

N3

N3-N2

Алгоритм Винограда

(N3+2N2)/2

(3N3+4N2-4N)/2

Алгоритм Штрассена

N2.81

6N2.81-6N2.

5.3. Вопросы для самоконтроля

  1. Вычисление значений многочленов стандартным способом.

  2. Вычисление значений многочленов по схеме Горнера.

  3. Стандартный алгоритм умножения матриц.

  4. Особенности умножения матриц по Винограду.

  5. Основная идея алгоритма Штрассена для умножения матриц.

6. Алгоритмы сравнения с образцами

Поиск подстроки в длинном тексте - важный элемент текстовых редакторов. Поиск по образцу можно применять не только в текстовых строках, но и для поиска битовых или байтовых строк в двоичном файле. Так, например, осуществляется поиск вирусов в памяти компьютера.

В программе обработки текстов обычно имеется функция проверки синтаксиса, которая не только обнаруживает неправильно написанные слова, но и предлагает варианты их правильного написания.

6.1. Сравнение строк

Необходимо найти первое вхождение некоторой подстроки в длинном тексте.

Стандартный алгоритм начинает со сравнения первого символа текста с первым символом подстроки. Если они совпадают, то происходит переход ко второму символу текста и подстроки.

При совпадении сравниваются следующие символы. Так продолжается до тех пор, пока не окажется, что подстрока целиком совпала с отрезком текста, или пока не встретятся несовпадающие символы.

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

Пример 6.1 Поиск подстроки (РЫБАК) в соответствующем тексте.

Текст РЫБА РЫБАКА ВИДИТ

подстрока РЫБАК

Р

ы

б

а

р

ы

б

а

к

а

в

и

д

и

т

р

ы

б

а

к

1 проход, 5 сравнений

р

2 проход, 1 сравнение

р

3 проход, 1 сравнение

р

4 проход, 1 сравнение

р

5 проход, 1 сравнение

р

ы

б

а

к

6 проход, 5 сравнений

Итого:

14 сравнений, слово найдено

SimpleSearch (Text, Substring)

// PS - указатель текущего сравнения символа в подстроке

// PT - указатель текущего сравн. символа в тексте

// Start - указатель на начало сравнения в тексте

pS = 1; pt = 1; Start = 1

Start

While pT  length (text) and pS  length (substring) do

if text(pt) = substr(pS) then // есть очередное совпадение

pt = pt + 1; pS = pS + 1

else // начато сравнение заново с текущим символом

start = start +1; pt = start; pS = 1

end if

end while

if ps > length (substr)

then return (start) // совпадение найдено

else return (0) // совпадение не найдено

endif

Наилучший случай тот, где искомое слово встречается с самого первого символа строки и fА (N)= NS сравнений, где NS - длина подстроки

Наихудший случай - при каждом проходе совпадают все символы, кроме последнего (например, в строке «хххх…х» искать «хххху»). В этом случае число сравнений fА (N)=(NT-NS+1)NS, где NT – длина строки текста.

Асимптотическая оценка сложности простого алгоритма – О(NT* NS).

Проблема стандартного алгоритма заключается в том, что он затрачивает много усилий впустую. Если сравнение начала подстроки уже произошло, то полученную информацию можно использовать для того, чтобы определить позицию следующего сравнения. Например, в вышеприведенном примере в искомой подстроке буква «Р» встречается 1 раз. Мы сделали 5 сравнений при первом проходе, получили отрицательный результат, следовательно, можно сразу сдвинуть точку Start на 5 (пять!) позиций вправо.