Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
11-15 питання.docx
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
42 Кб
Скачать
☆

13 Питання Прямий алгоритм пошуку

Одним з найпростіших методів пошуку є послідовне порівняння першого символу s з символами масиву a. Якщо наявний збіг, тоді порівнюються другі, треті,... символи аж до повного збігу рядка s з частиною вектору такої ж довжини, або до незбігу у деякому символі. Тоді пошук продовжується з наступного символу масиву a та першого символу рядку s. Це визначається елементарною програмою:

i = 0; // номер символу масиву a

while (i < N - lenghts)

{

j = 0; // номер символу рядка s

while ((s[j] == a[i+j]) && (j<lenghts)

j++;

if (j==lenghts)

return i; // успіх

}

Якщо збіги відбуватимуться досить часто, то час роботи програми може бути досить значним.

Існує варіант удосконалення цього алгоритму – це починати пошук після часткового збігу не з наступного елементу масиву, а з символу, наступного після тих, що переглядалися, якщо у рядку s немає фрагментів, що повторюються.

j = 0; // j - номер символа у a

found = false;

while (!found)

{

i = 0; // i - номер символа у s

while ((s[i] == a[j]) && (s[i] != ‘/0’)

{

i++;

j++;

};

if (s[i] == ‘/0’

found = true;

else

j -= i-1;

};

Алгоритм Боуєра та Мура

КМП-пошук дає справжній виграш тільки тоді, коли невдачі передувала деяка кількість збігів. Лише у цьому випадку слово зсовується більше ніж на одиницю. На жаль, це швидше виняток, ніж правило: збіги зустрічаються значно рідше, ніж незбіги. Тому виграш від практичного використання КМП-стратегії в більшості випадків пошуку в звичайних текстах досить незначний. Метод, який запропонували Р. Боуєр і Д. Мур в 1975 р., не тільки покращує обробку самого поганого випадку, але й дає виграш в проміжних ситуаціях.

БМ-пошук базується на незвичних міркуваннях – порівняння символів починається з кінця слова, а не з початку. Як і у випадку КМП-пошуку, слово перед фактичним пошуком трансформується в деяку таблицю. Нехай для кожного символу x із алфавіту величина dx – відстань від самого правого в слові входження x до правого кінця слова. Уявимо, що виявлена розбіжність між словом і текстом. У цьому випадку слово відразу ж можна зсунути праворуч на dpM-1 позицій, тобто на кількість позицій, швидше за все більше одиниці. Якщо символ, який не збігся, тексту в слові взагалі не зустрічається, то зсув стає навіть більшим, а саме зсовувати можна на довжину всього слова. Ось приклад, який ілюструє цей процес:

ABCABCABFABCABD

ABCABD

ABCABD

ABCABD

На початку роботи слід завести масив, який зберігав би для кожного символу, що може зустрітися у масиві a, значення зсуву. Для символів, що взагалі не зустрічаються у образі s, зсув дорівнює M – довжині образу. Для символів, що зустрічаються у s, зсув буде меншим, щоби не пропустити можливих попадань.

Програму можна записати таким чином.

for (ch=0; ch<256; ch++)

d[ch] = M; // замовчування

for (i=0; i<M-1; i++)

d[s[i]] = M-i-1; // уточнення

// Поиск слова p в тексте s

i = M;

do

{

j = M;

k = i;

do // Цикл порівняння символів

{

k--;

j---; // слова, начинаючи з правого

while ( (j<0) || (a[j]!=s[k]) ); //Вихід, при порівн. все слово або незбіг

i += d[s[i-1]]; // Зсув слова вправо

while ( (j<0) || (i>N));

У випадку постійних незбігів цей алгоритм робить одне порівняння на M символів.

Варто сказати, що запропоновані методи пошуку послідовностей можна модифікувати таким чином, щоб у кожному рядку пошук йшов не до кінця кожного рядка, а на кількість шуканих символів менше, бо слово s не може бути розташоване у кінці одного рядка та на початку наступного.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]