Алгоритм Кнута-Мориса-Пратта
Приблизительно в 1970 году ученые Кнут, Морис и Пратт изобрели алгоритм, фактически требующий только N сравнений даже в самом плохом случае. Идея алгоритма в том, что, начиная каждый раз сравнение образца с самого начала, можем уничтожать полезную информацию. После частичного совпадения начальной части образца с соответствующими символами текста фактически известна пройденная часть текста и можно «вычислить» некоторые сведения (на основе самого образца), с помощью которых потом быстро продвинемся по тексту.
Слово z - граница слова w, если существуют u и v: w=uz=zv, т.е. z - одновременно префикс и суффикс w.
Для произвольного слова X рассмотрим все его границы, и выберем среди них самую длинную (не считая самого X). Обозначим ее L(X). Например, L(abcab)=ab, L(cabcabc)=cabc. Функцию F(X), задающую длину максимальной границы слова X, будем называть префикс-функцией. Например, F(abcab)=2, F(cabcabc)=4.
Для вычисления сдвига D, нам понадобится вычислить значения F() для всех границ искомого образца. Например, для образца ABDABD в массиве d окажутся значения: -1,-1,-1,0,1,2. Это значит, что при несовпадении на i-ой позиции образец можно подвинуть по тексту на:
0: 0 - (-1) = 1 1: 1 – (-1) = 2 2: 2 – (-1) = 3 3: 3 – 0 = 3
void CompF(char* pat, int*d){
int i, len;
i=0;
d[0]=-1;
for(i=1; pat[i]!=0; i++){
len = d[i-1];
while (len>-1 && pat[len+1]!=pat[i])
len = d[len];
if (pat[len+1] == pat[i]) d[i]=len+1;
else d[i]=-1; }
}
int FindKMP (char* text,char* pat ){
int i, j, lenT, lenP, d[100];
lenT = strlen(text);
lenP = strlen(pat);
CompF(pat, d);
for (i=0,j=-1; i < lenT; i++) {
while (j>=0 && text[i]!=pat[j+1]) j = d[j];
if (text[i] == pat[j+1]) j++;
if (j+1==lenP) return i-lenP+1;}
return 0;}
Алгоритм Бойера-Мура
Рассмотрим алгоритм, который не только улучшает обработку самого плохого случая, но и дает выигрыш в промежуточных ситуациях. Его предложили Боуер и Мур примерно в 1975 году. Сравнение символов начинается с конца, образ сначала трансформируется в некоторую таблицу.
Пусть для каждого символа х из алфавита dх – расстояние от самого правого в образе вхождения х до его конца (правого). Пусть возникло расхождение между образом и строкой. В этом случае образ сразу же можно сдвинуть вправо на dpM-1 позиций, т.е. на число позиций, скорее всего больше 1.
#define ASIZE 256
int BM(char* text, char *pattern, int n, int m){
int i,d[ASIZE];
for (i=0;i<ASIZE;i++)
d[i] = m + 1;// если такой буквы нет, сдвигаемся на длину слова
for (i=0;i<m;i++)
d[pattern[i]] = m - i;
i = 0;
while (i <= n - m)
{
if (memcmp(&text[i],pattern,m) == 0) //сравнивает, 0 - равны
return i;
i = i + d[text[i + m]];
}
return -1;
}
void main()
{
char text[100], pattern[100];
printf("\nInput text:\n");
gets(text);
printf("\nInput pattern:\n");
gets(pattern);
int a=BM( text, pattern, strlen(text), strlen(pattern) );
printf("%d",a);
getch();}
Сравнительный анализ известных алгоритмов
Алгоритм |
Время на предварит. обработку |
Среднее время поиска |
Худшее время поиска |
Примечания |
Алгоритм прямого сравнения |
Нет |
2*n |
O(n*m) |
Mалые трудозатраты на программу |
Алгоритм KMP |
O(m) |
O(n+m) |
O(n+m) |
- |
Алгоритм БМ |
O(m+s) |
O(n+m) |
O(n*m) |
Алгоритмы этой группы наиболее эффективны в обычных ситуациях. Быстродействие повышается при увеличении образца или алфавита. |
Сортировки – общая классификация
Задача сортировки состоит в перестановке членов последовательности таким образом, чтобы выполнялось условие: ai <= ai+1, для всех i от 0 до n.
Если значение функции сравнения зависит только от поля x, то x называют ключом, по которому производится сортировка.
1. Время сортировки - основной параметр, характеризующий быстродействие алгоритма.
2. Память - ряд алгоритмов требует выделения дополнительной памяти под временное хранение данных. При оценке используемой памяти не будет учитываться место, которое занимает исходный массив и независящие от входной последовательности затраты, например, на хранение кода программы.
3. Устойчивость - устойчивая сортировка не меняет взаимного расположения равных элементов.
4. Естественность поведения - эффективность метода при обработке уже отсортированных, или частично отсортированных данных. Алгоритм ведет себя естественно, если учитывает эту характеристику входной последовательности и работает лучше.
Еще одним важным свойством алгоритма является его сфера применения: внутренние сортировки (работают с данным в оперативной памяти с произвольным доступом), внешние сортировки (упорядочивают информацию, расположенную на внешних носителях). Это накладывает некоторые дополнительные ограничения на алгоритм: доступ к носителю осуществляется последовательным образом: в каждый момент времени можно считать или записать только элемент, следующий за текущим, объем данных не позволяет им разместиться в ОЗУ. Кроме того, доступ к данным на носителе производится намного медленнее, чем операции с оперативной памятью.
Внутренняя сортировка оперирует с массивами, целиком помещающимися в оперативной памяти с произвольным доступом к любой ячейке. Данные обычно сортируются на том же месте, без дополнительных затрат.
Внешняя сортировка оперирует с запоминающими устройствами большого объема, но с доступом не произвольным, а последовательным (сортировка файлов), т.е. в данный момент «видим» только один элемент, а затраты на перемотку по сравнению с памятью неоправданно велики. Это приводит к специальным методам сортировки, обычно использующим дополнительное дисковое пространство.
Займемся сначала прямыми методами сортировок, в которых требуется порядка n2 сравнений ключей. Усложненные методы требуют небольшого числа операций, но эти операции обычно сами более сложны, и поэтому для достаточно малых n прямые методы оказываются быстрее, хотя для больших n их использовать не следует.