Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "pch.h"
- #include <iostream>
- #include <thread>
- #include <string>
- #include <vector>
- std::vector<size_t> prefix_function(const std::string& haystack);
- std::vector<size_t> knuth_morris_pratt(const std::string& haystack, const std::string& needle, char salt);
- class KnuthMorrisPrattCompressed
- {
- public:
- static std::vector<size_t> find(const std::string& haystack, const std::string& needle);
- };
- #define FUTILITY
- std::vector<size_t> prefix_function(const std::string& haystack) {
- #ifdef FUTILITY
- std::cout << "calculation of prefix-function..." << std::endl;
- std::cout << "prefix-function value for first character: " << haystack.front() << " equal to: 0" << std::endl << std::endl;
- #endif
- std::vector<size_t> result(haystack.length());
- for (size_t i = 1; i < haystack.length(); ++i)
- {
- #ifdef FUTILITY
- std::cout << "current character: " << haystack[i] << " (index i: " << i << ")" << std::endl;
- #endif
- // by default, result is filled with zeros
- size_t j = result[i - 1];
- #ifdef FUTILITY
- std::cout << "last known prefix-function value j: " << j << std::endl;
- #endif
- // осуществляем возврат по известным значениям префикс функции
- while (j > 0 && haystack[i] != haystack[j])
- {
- j = result[j - 1];
- #ifdef FUTILITY
- std::cout << "s[i] not equal to s[j]: decreasing j: " << j << std::endl;
- #endif
- }
- // увеличиваем значение профекс функции на единицу
- if (haystack[i] == haystack[j])
- {
- ++j;
- #ifdef FUTILITY
- std::cout << "character are equal: incrementing j: " << j << std::endl;
- #endif
- }
- #ifdef FUTILITY
- std::cout << "prefix-function value found: " << j << std::endl << std::endl;
- #endif
- result[i] = j;
- }
- #ifdef FUTILITY
- std::cout << "calculation of prefix-function ends" << std::endl;
- #endif
- // using move semantics
- return std::move(result);
- }
- std::vector<size_t> knuth_morris_pratt(const std::string& haystack, const std::string& needle, char salt) {
- std::vector<size_t> result;
- std::vector<size_t> prefix = prefix_function(needle + salt + haystack);
- #ifdef FUTILITY
- std::cout << "prefix-function prefix-function values: " << std::endl;
- for (size_t i = 0; i < needle.length(); ++i)
- std::cout << needle[i] << " ";
- std::cout << salt << " ";
- for (size_t i = 0; i < haystack.length(); ++i)
- std::cout << haystack[i] << " ";
- std::cout << std::endl;
- for (size_t i = 0; i < prefix.size(); ++i)
- std::cout << prefix[i] << " ";
- std::cout << std::endl;
- #endif
- for (size_t i = 0; i < haystack.length(); ++i)
- {
- // найдено вхождение
- if (prefix[needle.length() + i + 1] == needle.length())
- {
- // добавляем индекс в выходные данные с учётом сдвига
- result.push_back(i + 1 - needle.length());
- }
- }
- // using move semantics
- return std::move(result);
- }
- std::vector<size_t> KnuthMorrisPrattCompressed::find(const std::string& haystack, const std::string& needle)
- {
- std::vector<size_t> entries;
- size_t p = needle.length();
- size_t t = haystack.length();
- if (p > t || p == 0)
- return (std::move(entries));
- std::vector<size_t> prefix = prefix_function(needle);
- #ifdef FUTILITY
- std::cout << "prefix-function prefix-function values: " << std::endl;
- for (size_t i = 0; i < needle.length(); ++i)
- std::cout << needle[i] << " ";
- std::cout << std::endl;
- for (size_t i = 0; i < prefix.size(); ++i)
- std::cout << prefix[i] << " ";
- std::cout << std::endl;
- #endif
- for (size_t i = 0, k = 0; i < t; ++i)
- {
- while (true)
- {
- if (haystack[i] == needle[k])
- {
- ++k;
- if (k == p)
- entries.push_back(i + 1 - p);
- break;
- }
- if (k == 0)
- break;
- k = prefix[p - 1];
- }
- }
- return (std::move(entries));
- }
- int main() {
- std::string needle;
- std::cin >> needle;
- std::string haystack;
- std::cin >> haystack;
- std::vector<size_t> entries = KnuthMorrisPrattCompressed::find(haystack, needle);
- // no entries found
- if (entries.empty())
- {
- std::cout << -1 << std::endl << std::endl;
- return EXIT_SUCCESS;
- }
- for (size_t i = 0; i < entries.size() - 1; ++i)
- std::cout << entries[i] << ',';
- std::cout << entries.back() << std::endl << std::endl;
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement