Скачиваний:
1
Добавлен:
22.09.2026
Размер:
71 Кб
Скачать
☆

Приложение. Листинг программных модулей

#include <iostream>

#include <vector>

#include <string>

#include <chrono>

#include <cstdlib>

#include <ctime>

#include <iomanip>

using namespace std;

using namespace chrono;

// Алфавит из 6 символов (a-f)

const string ALPHABET = "abcdef";

// Фиксированный паттерн

const string PATTERN = "abbfedfa";

const int PAT_LEN = PATTERN.size();

// Генерация случайного символа из алфавита

char getRandomChar() {

return ALPHABET[rand() % ALPHABET.size()];

}

// Генерация случайной строки длины len

string random_string(int len) {

string s(len, ' ');

for (int i = 0; i < len; ++i)

s[i] = getRandomChar();

return s;

}

// Генерация текста

string generate_text(int L) {

string text = random_string(L);

int start = rand() % (L - PAT_LEN + 1);

int pos = start;

while (pos <= L - PAT_LEN) {

for (int i = 0; i < PAT_LEN; ++i)

text[pos + i] = PATTERN[i];

int period = 10 + rand() % 11; // 10..20

pos += period;

}

return text;

}

// Наивный поиск

int find_substrings(const string& S, const string& W) {

unsigned int i, j;

int number = 0;

for (i = 0; i < S.length() - W.length() + 1; i++) {

j = 0;

while ((j < W.length()) && (W[j] == S[i + j])) {

j = j + 1;

}

if (j == W.length()) {

number++;

}

}

return number;

}

// КМП

int KMPSearch(const string& text, const string& pattern) {

int n = text.length();

int m = pattern.length();

int count = 0;

// Создаем префикс-функцию

vector<int> pi(m);

pi[0] = 0;

int k = 0;

for (int i = 1; i < m; i++) {

while (k > 0 && pattern[k] != pattern[i])

k = pi[k - 1];

if (pattern[k] == pattern[i])

k++;

pi[i] = k;

}

// Поиск подстроки

k = 0;

for (int i = 0; i < n; i++) {

while (k > 0 && pattern[k] != text[i])

k = pi[k - 1];

if (pattern[k] == text[i])

k++;

if (k == m) {

count++;

k = pi[k - 1]; // продолжаем поиск

}

}

return count;

}

int main() {

srand(static_cast<unsigned>(time(nullptr)));

// Параметры эксперимента

const int MIN_LEN = 100;

const int MAX_LEN = 2000;

const int STEP = 100;

const int NUM_TEXTS = 20; // число разных текстов для каждой длины

const int REPEATS_PER_TEXT = 500; // число повторений на каждом тексте

cout << fixed << setprecision(3);

cout << "Length\tNaive (micros)\tKMP (micros)\n";

for (int L = MIN_LEN; L <= MAX_LEN; L += STEP) {

double naive_total_time = 0;

double kmp_total_time = 0;

long long naive_total_count = 0;

long long kmp_total_count = 0;

for (int t = 0; t < NUM_TEXTS; ++t) {

// Генерируем новый текст

string text = generate_text(L);

// Измеряем overhead пустого цикла

auto start = high_resolution_clock::now();

for (int r = 0; r < REPEATS_PER_TEXT; ++r) {

volatile int dummy = 0;

(void)dummy;

}

auto end = high_resolution_clock::now();

double loop_overhead = duration<double, micro>(end - start).count();

// Наивный поиск

start = high_resolution_clock::now();

for (int r = 0; r < REPEATS_PER_TEXT; ++r) {

naive_total_count += find_substrings(text, PATTERN);

}

end = high_resolution_clock::now();

naive_total_time += (duration<double, micro>(end - start).count() - loop_overhead);

// КМП поиск

start = high_resolution_clock::now();

for (int r = 0; r < REPEATS_PER_TEXT; ++r) {

kmp_total_count += KMPSearch(text, PATTERN);

}

end = high_resolution_clock::now();

kmp_total_time += (duration<double, micro>(end - start).count() - loop_overhead);

}

// Проверка корректности

if (naive_total_count != kmp_total_count) {

cerr << "Mismatch at L=" << L << ": naive=" << naive_total_count

<< ", kmp=" << kmp_total_count << endl;

}

// Усредняем

double naive_avg = naive_total_time / (NUM_TEXTS * REPEATS_PER_TEXT);

double kmp_avg = kmp_total_time / (NUM_TEXTS * REPEATS_PER_TEXT);

// Вывод

cout << L << "\t" << naive_avg << "\t\t" << kmp_avg << "\n";

}

return 0;

}

Соседние файлы в папке Отчёты Дагаев