Cod sursa(job #473514)

Utilizator ilie.danilaIlie Teodor Danila ilie.danila Data 29 iulie 2010 22:32:26
Problema Potrivirea sirurilor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.33 kb
#include <fstream>
#include <string>
#include <vector>

using namespace std;

class PatternMatcher{
public:
    static vector<int> kmpSearch(const string& text, const string& pattern);

private:
    static vector<int> computeKmpPrefix(const string& pattern);

    PatternMatcher();
    PatternMatcher(const PatternMatcher&);
    const PatternMatcher& operator=(const PatternMatcher&);
};

vector<int> PatternMatcher::computeKmpPrefix(const std::string &pattern){
    int patternSize = pattern.size();
    vector<int> kmpPrefix(patternSize);
    size_t prefixPos = 0;
    size_t suffixPos = 1;

    while(suffixPos < patternSize){
        if(pattern[prefixPos] == pattern[suffixPos]){
            kmpPrefix[suffixPos] = prefixPos + 1;
            prefixPos++;
            suffixPos++;
        }
        else if(prefixPos > 0){//found some match
            prefixPos = kmpPrefix[prefixPos -1];//backtrack for matching prefix e.g. aaaaabaaaaaa
        }
        else{
            kmpPrefix[suffixPos] = 0;
            suffixPos++;
        }
    }
    return kmpPrefix;
}

vector<int> PatternMatcher::kmpSearch(const std::string &text, const std::string &pattern){

    size_t textSize = text.size();
    size_t patternSize = pattern.size();

    /*if(patternSize > textSize)
        return -1;*/

    vector<int> kmpNext = computeKmpPrefix(pattern);
    int tIdx = 0;
    int pIdx = 0;

    vector<int> solutions;

    while(tIdx < textSize){
        if(pattern[pIdx] == text[tIdx]){
            if(pIdx == patternSize - 1)
            {
                //return tIdx - (patternSize - 1);    //index where the last comparison was ok
                solutions.push_back( tIdx - (patternSize - 1) );
                tIdx = tIdx - (patternSize - 2) ;
                pIdx = 0;
            }
            tIdx++;
            pIdx++;
        }
        else if(pIdx > 0){
            pIdx = kmpNext[pIdx - 1];
        }
        else{
            tIdx++;
        }
    }
    //return -1;
    return solutions;
}

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

    string needle;
    string haystack;

    f >> needle >> haystack;

    f.close();

    vector<int> solutions =PatternMatcher::kmpSearch(haystack, needle);

    g << solutions.size() << "\n";
    for( int i = 0; i < solutions.size(); i++ )
        g << solutions[i] << " ";
    g << "\n";

    return 0;
}