Cod sursa(job #1833176)

Utilizator Stefex09Stefan Teodorescu Stefex09 Data 21 decembrie 2016 20:56:16
Problema Potrivirea sirurilor Scor 78
Compilator cpp Status done
Runda Arhiva educationala Marime 3.68 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>

using namespace std;

static const int MAX_LENGTH = 2000000;

enum StringMatcherType {
    KNUTH_MORRIS_PRATT,
    RABIN_KARP,
    BRUTE_FORCE,
};

class StringMatcher {
public:
    StringMatcher(char *needle, char *haystack) : needle(needle), haystack(haystack) { }
    virtual ~StringMatcher() { }

    virtual vector<int> findMatches() = 0;

protected:
    char* needle;
    char* haystack;
};

class KMP : public StringMatcher {
private:
    void buildPrefix(const char* string, const int& length, int* prefix)
    {
        int index = 0;

        prefix[0] = 0;

        for (int i = 1; i < length; ) {
            if (string[i] == string[index]) {
                prefix[i] = index + 1;
                index++;
                i++;
            } else {
                if (index != 0) {
                    index = prefix[index - 1];
                } else {
                    prefix[i] = 0;
                    i++;
                }
            }
        }
    }

public:
    vector<int> findMatches() override {
        int needleLength = strlen(needle);
        int haystackLength = strlen(haystack);

        int *prefix = new int[needleLength];

        buildPrefix(needle, needleLength, prefix);

        int index = 0;
        vector<int> solutions;
        for (int i = 0; i < haystackLength; ) {
            if (haystack[i] == needle[index]) {
                index++;
                i++;
            } else {
                if (index != 0) {
                    index = prefix[index - 1];
                } else {
                    i++;
                }
            }

            if (index == needleLength) {
                solutions.push_back(i - needleLength);
                index = prefix[index - 1];
            }
        }

        if (index == needleLength - 1) {
            solutions.push_back(haystackLength - needleLength + 1);
        }

        delete prefix;

        return solutions;
    }

public:
    KMP(char *needle, char *haystack) : StringMatcher(needle, haystack) { }
};

class StringMatcherFactory {
private:
    StringMatcherFactory() { }
    static StringMatcherFactory *instance;
    char* needle;
    char* haystack;

public:
    static StringMatcherFactory* getInstance() {
        if (StringMatcherFactory::instance == nullptr) {
            StringMatcherFactory::instance = new StringMatcherFactory();
        }

        return StringMatcherFactory::instance;
    }


    void setNeedle(char *needle) {
        this->needle = needle;
    }

    void setHaystack(char *haystack) {
        this->haystack = haystack;
    }

    StringMatcher* getMatcher(StringMatcherType type) {
        switch (type) {
            case KNUTH_MORRIS_PRATT:
                return new KMP(needle, haystack);
            default:
                return nullptr;
        }
    }
};

StringMatcherFactory* StringMatcherFactory::instance = nullptr;

int main() {
    ifstream in("strmatch.in");
    ofstream out("strmatch.out");

    char *needle, *haystack;
    needle = new char[MAX_LENGTH];
    haystack = new char[MAX_LENGTH];

    in.getline(needle, MAX_LENGTH);
    in.getline(haystack, MAX_LENGTH);

    StringMatcherFactory* factory = StringMatcherFactory::getInstance();
    factory->setHaystack(haystack);
    factory->setNeedle(needle);

    StringMatcher* kmpSolver = factory->getMatcher(KNUTH_MORRIS_PRATT);
    vector<int> solutions = kmpSolver->findMatches();

    out << solutions.size() << "\n";
    int show = min((int) solutions.size(), 1000);
    for (int i = 0; i < show; i++) {
        out << solutions[i] << " ";
    }

    delete needle;
    delete haystack;
    delete kmpSolver;

    in.close();
    out.close();

    return 0;
}