Advertisement
iawitm

Untitled

Apr 15th, 2019
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.37 KB | None | 0 0
  1. #include "stdafx.h"
  2.  
  3. #include <iostream>
  4.  
  5. #include <algorithm>
  6.  
  7. #include <string>
  8.  
  9. #include <vector>
  10.  
  11.  
  12. #
  13. define ALPHABET_LENGTH 256
  14.  
  15. using namespace std;
  16.  
  17. bool compareWithRegister(char a, char b) {
  18.   return (a == b);
  19.  
  20. }
  21.  
  22. bool compareWithoutRegister(char a, char b) {
  23.   return (tolower(a) == tolower(b));
  24.  
  25. }
  26.  
  27. // Префикс-функция
  28. vector < int > prefixFunction(string substr, bool reg) {
  29.   vector < int > d;
  30.   d.reserve(substr.length());
  31.   for (int i = 0; i < substr.length(); i++) {
  32.     d.push_back(0);
  33.   }
  34.   int i = 1;
  35.   int j = 0;
  36.   if (reg) {
  37.     while (i < substr.length()) {
  38.       if (compareWithRegister(substr[i], substr[j])) {
  39.         d[i] = j + 1;
  40.         i++;
  41.         j++;
  42.       } else {
  43.         if (j == 0) {
  44.           d[i] = 0;
  45.           i++;
  46.         } else {
  47.           j = d[j - 1];
  48.         }
  49.  
  50.       }
  51.     }
  52.   } else {
  53.     while (i < substr.length()) {
  54.       if (compareWithoutRegister(substr[i], substr[j])) {
  55.         d[i] = j + 1;
  56.         i++;
  57.         j++;
  58.       } else {
  59.         if (j == 0) {
  60.           d[i] = 0;
  61.           i++;
  62.         } else {
  63.           j = d[j - 1];
  64.         }
  65.  
  66.       }
  67.     }
  68.   }
  69.  
  70.   return d;
  71.  
  72. }
  73.  
  74. // Сама функция поиска КМП
  75. void searchKMP(string str, string substr, bool reg) {
  76.   int iterations = 0;
  77.   vector < int > d;
  78.   d.reserve(substr.length());
  79.   d = prefixFunction(substr, reg);
  80.   int k = 0;
  81.   int l = 0;
  82.   if (reg) {
  83.     while ((k != str.length()) && (l != substr.length())) {
  84.       if (compareWithRegister(str[k], substr[l])) {
  85.         k++;
  86.         l++;
  87.         iterations++;
  88.       } else {
  89.         if (l == 0) k++;
  90.         else l = d[l - 1];
  91.         iterations++;
  92.       }
  93.     }
  94.  
  95.   } else {
  96.     while ((k != str.length()) && (l != substr.length())) {
  97.       if (compareWithoutRegister(str[k], substr[l])) {
  98.         k++;
  99.         l++;
  100.         iterations++;
  101.       } else {
  102.         if (l == 0) k++;
  103.         else l = d[l - 1];
  104.         iterations++;
  105.       }
  106.     }
  107.   }
  108.  
  109.   if ((k == str.length()) && (l != substr.length())) {
  110.     cout << "Not found with KMP" << endl;
  111.   } else {
  112.     cout << "Found with KMP, index: " << k - l << endl;
  113.   }
  114.   cout << "KMP iterations = " << iterations << endl;
  115.  
  116. }
  117.  
  118. // Таблица для БМ-алгоритм
  119. vector < int > bmTable(string substr, bool reg) {
  120.  
  121.   vector < int > d;
  122.   d.reserve(ALPHABET_LENGTH);
  123.   for (int i = 0; i < ALPHABET_LENGTH; i++)
  124.     d.push_back(-1);
  125.  
  126.   if (reg)
  127.     for (int i = substr.length() - 1; i > -1; i--)
  128.       d[substr[i]] = i;
  129.   else
  130.     for (int i = substr.length() - 1; i > -1; i--)
  131.       d[tolower(substr[i])] = i;
  132.  
  133.   return d;
  134. }
  135.  
  136. void bmSearch(string str, string substr, bool reg) {
  137.   int iterations = 0;
  138.   bool flag = false;
  139.   //Вычислить длину исходной строки
  140.   int n = str.length();
  141.  
  142.   //Вычислить длину образа
  143.   int m = substr.length();
  144.  
  145.   //Заполнить таблицу для этого алгоритма
  146.   vector < int > d;
  147.   d.reserve(ALPHABET_LENGTH);
  148.   d = bmTable(substr, reg);
  149.  
  150.   //Переменная смещения образа по отношению к тексту
  151.   int s = 0;
  152.   if (reg) {
  153.     //Пока s меньше, чем разность длины строки и образа
  154.     while (s <= (n - m)) {
  155.       int j = m - 1;
  156.  
  157.       //Если образ совпадает со строкой, начиная с конца
  158.       if ((j >= 0) && compareWithRegister(substr[j], str[s + j]))
  159.         while ((j >= 0) && compareWithRegister(substr[j], str[s + j])) {
  160.           j--; //Двигаться от конца образа
  161.           iterations++;
  162.         }
  163.       else {
  164.         iterations++;
  165.       }
  166.  
  167.       //Если образ полностью совпал со строкой
  168.       if (j < 0) {
  169.         cout << "found " << s << endl;
  170.         flag = true;
  171.  
  172.         //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  173.         //таким же символом в образе или на 1, если длины строки не хватает
  174.         if (reg)
  175.           s += ((s + m) < n) ? m - d[str[s + m]] : 1;
  176.         else
  177.           s += ((s + m) < n) ? m - d[tolower(str[s + m])] : 1;
  178.       } else {
  179.         //Сдвинуть образ так, чтобы символ в тексте, не совпавший с символом
  180.         //в образе, совпадал с последним таким же символом в образе или на 1,
  181.         //если совпадающий символ правее текущего символа в образе
  182.         if (reg) {
  183.           if (1 >= (j - d[str[s + j]])) {
  184.             s++;
  185.           } else {
  186.             s += j - d[str[s + j]];
  187.           }
  188.  
  189.         } else
  190.           s += (1 >= (j - d[tolower(str[s + j])])) ? 1 : (j - d[tolower(str[s + j])]);
  191.       }
  192.     }
  193.   } else {
  194.     while (s <= (n - m)) {
  195.       int j = m - 1;
  196.  
  197.       //Если образ совпадает со строкой, начиная с конца
  198.       if ((j >= 0) && compareWithRegister(substr[j], str[s + j]))
  199.         while ((j >= 0) && compareWithoutRegister(substr[j], str[s + j])) {
  200.           j--; //Двигаться от конца образа
  201.           iterations++;
  202.         }
  203.       else {
  204.         iterations++;
  205.       }
  206.  
  207.       //Если образ полностью совпал со строкой
  208.       if (j < 0) {
  209.         cout << "Found with BM, index " << s << endl;
  210.         flag = true;
  211.  
  212.         //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  213.         //таким же символом в образе или на 1, если длины строки не хватает
  214.         if (reg)
  215.           s += ((s + m) < n) ? m - d[str[s + m]] : 1;
  216.         else
  217.           s += ((s + m) < n) ? m - d[tolower(str[s + m])] : 1;
  218.       } else {
  219.         //Сдвинуть образ так, чтобы символ в тексте, не совпавший с символом
  220.         //в образе, совпадал с последним таким же символом в образе или на 1,
  221.         //если совпадающий символ правее текущего символа в образе
  222.         if (reg) {
  223.           if (1 >= (j - d[str[s + j]])) {
  224.             s++;
  225.           } else {
  226.             s += j - d[str[s + j]];
  227.           }
  228.  
  229.         } else
  230.           s += (1 >= (j - d[tolower(str[s + j])])) ? 1 : (j - d[tolower(str[s + j])]);
  231.       }
  232.     }
  233.   }
  234.   // flag нужен, чтобы нот фаунд не выводилось после успешного нахождения
  235.   if ((s > n - m) & !(flag))
  236.     cout << "Not found with BM" << endl;
  237.   cout << "BM iterations = " << iterations << endl;
  238. }
  239.  
  240. void bruteForceSearch(string str, string substr, bool reg) {
  241.   int iterations = 0;
  242.   bool flag = false;
  243.   int n = str.length();
  244.   int m = substr.length();
  245.  
  246.   if (reg) {
  247.  
  248.     //Пройти по строке
  249.     for (int i = 0; i < n - m + 1; i++) {
  250.       //Пройти по образу
  251.       for (int j = 0; j < m; j++) {
  252.         iterations++;
  253.         //Выйти из цикла прохода образа, если найдено несоответствие
  254.         if (!compareWithRegister(str[i + j], substr[j]))
  255.           break;
  256.  
  257.         //Если образ полностью совпал со строкой, то добавить индекс
  258.         if (j == m - 1) {
  259.           cout << i << endl;
  260.           flag = true;
  261.         }
  262.       }
  263.     }
  264.   } else {
  265.     //Пройти по строке
  266.     for (int i = 0; i < n - m + 1; i++) {
  267.       //Пройти по образу
  268.       for (int j = 0; j < m; j++) {
  269.         iterations++;
  270.         //Выйти из цикла прохода образа, если найдено несоответствие
  271.         if (!compareWithoutRegister(str[i + j], substr[j]))
  272.           break;
  273.  
  274.         //Если образ полностью совпал со строкой, то добавить индекс
  275.         if (j == m - 1) {
  276.           cout << "Found with BruteForce, index " << i << endl;
  277.           flag = true;
  278.         }
  279.       }
  280.     }
  281.   }
  282.   if (!flag)
  283.     cout << "Not found with BruteForce" << endl;
  284.   cout << "BruteForce iterations = " << iterations << endl;
  285. }
  286.  
  287. //Объединённый алгоритм поиска Кнута-Морриса-Пратта и Боуера-Мура
  288. void KMPAndBMSearch(string str, string substr, bool reg) {
  289.   int n = str.length();
  290.   int m = substr.length();
  291.  
  292.   //Заполнить таблицу d
  293.   vector < int > d = prefixFunction(substr, reg);
  294.  
  295.   //Заполнить таблицу Боуера-Мура
  296.   vector < int > bmT = bmTable(substr, reg);
  297.  
  298.   //Переменная смещения образа по отношению к тексту
  299.   int s = 0;
  300.  
  301.   if (reg) {
  302.     //Пока s меньше, чем разность длины строки и образа
  303.     while (s <= (n - m)) {
  304.       int j = m - 1;
  305.  
  306.       //Пока образ совпадает со строкой, начиная с конца
  307.       while ((j >= 0) && compareWithRegister(substr[j], str[s + j]))
  308.         j--; //Двигаться от конца образа
  309.  
  310.       //Если образ полностью совпал со строкой
  311.       if (j < 0) {
  312.         cout << "Found, index " << s << endl;
  313.  
  314.         int k = m;
  315.         while ((k > 0) && !compareWithRegister(substr[k], str[m]))
  316.           k = d[k - 1];
  317.  
  318.         //Если сдвиг Кнута-Морриса-Пратта больше, чем сдвиг Боуера-Мура
  319.         if (k > (m - bmT[str[s + m]]))
  320.           s += ((s + k) < n) ? k : 1;
  321.         //Иначе
  322.         else
  323.           //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  324.           //таким же символом в образе
  325.           if (reg)
  326.             s += ((s + m) < n) ? (m - bmT[str[s + m]]) : 1;
  327.           else
  328.             s += ((s + m) < n) ? (m - bmT[tolower(str[s + m])]) : 1;
  329.       }
  330.       //Иначе
  331.       else {
  332.         int i = s + j;
  333.         int k = j;
  334.         while ((k > 0) && !compareWithRegister(substr[k], str[i]))
  335.           k = d[k - 1];
  336.  
  337.         if (reg) {
  338.           //Если сдвиг Кнута-Морриса-Пратта больше, чем сдвиг Боуера-Мура
  339.           if (k > (j - bmT[str[s + j]]))
  340.             s += ((s + k) < n) ? k : 1;
  341.           //Иначе
  342.           else
  343.             //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  344.             //таким же символом в образе
  345.             s += ((j - bmT[str[s + j]]) <= 1) ? 1 : (j - bmT[str[s + j]]);
  346.         } else {
  347.           //Если сдвиг Кнута-Морриса-Пратта больше, чем сдвиг Боуера-Мура
  348.           if (k > (j - bmT[tolower(str[s + j])]))
  349.             s += ((s + k) < n) ? k : 1;
  350.           //Иначе
  351.           else
  352.             //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  353.             //таким же символом в образе
  354.             s += ((j - bmT[tolower(str[s + j])]) <= 1) ? 1 : (j - bmT[tolower(str[s + j])]);
  355.         }
  356.       }
  357.     }
  358.   } else {
  359.     //Пока s меньше, чем разность длины строки и образа
  360.     while (s <= (n - m)) {
  361.       int j = m - 1;
  362.  
  363.       //Пока образ совпадает со строкой, начиная с конца
  364.       while ((j >= 0) && compareWithoutRegister(substr[j], str[s + j]))
  365.         j--; //Двигаться от конца образа
  366.  
  367.       //Если образ полностью совпал со строкой
  368.       if (j < 0) {
  369.         cout << "Found, index " << s << endl;
  370.  
  371.         int k = m;
  372.         while ((k > 0) && !compareWithoutRegister(substr[k], str[m]))
  373.           k = d[k - 1];
  374.  
  375.         //Если сдвиг Кнута-Морриса-Пратта больше, чем сдвиг Боуера-Мура
  376.         if (k > (m - bmT[str[s + m]]))
  377.           s += ((s + k) < n) ? k : 1;
  378.         //Иначе
  379.         else
  380.           //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  381.           //таким же символом в образе
  382.           if (reg)
  383.             s += ((s + m) < n) ? (m - bmT[str[s + m]]) : 1;
  384.           else
  385.             s += ((s + m) < n) ? (m - bmT[tolower(str[s + m])]) : 1;
  386.       }
  387.       //Иначе
  388.       else {
  389.         int i = s + j;
  390.         int k = j;
  391.         while ((k > 0) && !compareWithoutRegister(substr[k], str[i]))
  392.           k = d[k - 1];
  393.  
  394.         if (reg) {
  395.           //Если сдвиг Кнута-Морриса-Пратта больше, чем сдвиг Боуера-Мура
  396.           if (k > (j - bmT[str[s + j]]))
  397.             s += ((s + k) < n) ? k : 1;
  398.           //Иначе
  399.           else
  400.             //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  401.             //таким же символом в образе
  402.             s += ((j - bmT[str[s + j]]) <= 1) ? 1 : (j - bmT[str[s + j]]);
  403.         } else {
  404.           //Если сдвиг Кнута-Морриса-Пратта больше, чем сдвиг Боуера-Мура
  405.           if (k > (j - bmT[tolower(str[s + j])]))
  406.             s += ((s + k) < n) ? k : 1;
  407.           //Иначе
  408.           else
  409.             //Сдвинуть образ так, чтобы следующий символ в тексте совпадал с последним
  410.             //таким же символом в образе
  411.             s += ((j - bmT[tolower(str[s + j])]) <= 1) ? 1 : (j - bmT[tolower(str[s + j])]);
  412.         }
  413.       }
  414.     }
  415.   }
  416. }
  417.  
  418. int main() {
  419.  
  420.   string str = "Hola-Hola girls like Hooligans";
  421.   string substr = "hooligans";
  422.  
  423.   searchKMP(str, substr, false);
  424.   bmSearch(str, substr, false);
  425.   bruteForceSearch(str, substr, false);
  426.   KMPAndBMSearch(str, substr, false);
  427.   system("PAUSE");
  428.   return 0;
  429. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement