Cod sursa(job #2325518)

Utilizator manciu_ionIon Manciu manciu_ion Data 22 ianuarie 2019 18:30:48
Problema Potrivirea sirurilor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.67 kb
#include <iostream>
#include <fstream>

using namespace std;

const int kMaxMessageLength = 100003;
const int kAlphabetSize = 10000;

const char kInputFile[] = "cifru2.in";
const char kOutputFile[] = "cifru2.out";

const int kHashKeys[] = {1000003, 1000033};
const int kBase = 10007;

ifstream inputfile(kInputFile);
ofstream outputfile(kOutputFile);

int distmessage[2 * kMaxMessageLength];
int distmessagecode[kMaxMessageLength];
int message[kMaxMessageLength];
int messagecode[kMaxMessageLength];
int alphabet[kAlphabetSize];
int lengthofmessage;
int lengthalphabet;

void ReadInputData();
void WriteOutputData();
void ConcatArray(int array[], int arraysize);
void PrinteArray(int array[], int arraysize);
int Pow(int number, int exponent, int modulo);
void SetAlphabet(int shift, int length, int dest[]);
pair<int, int> GetHashes(int source[], int srclength);
void SetDistaces(int source[], int destination[], int destsize);
void ComputeLPSArray(int pattern[], int patternsize, int lpsarray[]);
int GetMatchingPosition(int source[], int destination[], int srclength, int destlength);
int FindMatchingPosition(int source[], int destination[], int srclength, int destlength);

int main(){

    ios::sync_with_stdio( false );

    ReadInputData();

    SetDistaces(message, distmessage, lengthofmessage);
    //PrinteArray(distmessage, lengthofmessage);

    ConcatArray(distmessage, lengthofmessage);
    //PrinteArray(distmessage, 2 * lengthofmessage);

    SetDistaces(messagecode, distmessagecode, lengthofmessage);
    //PrinteArray(distmessagecode, lengthofmessage);

    WriteOutputData();

    inputfile.close();
    outputfile.close();
    return 0;
}

void SetAlphabet(int shift, int length, int dest[]){
    int head = shift;
    for (int ind = 1; ind <= length; ++ind) {
        ++head;
        if (head > length) {
            head = 1;
        }
        dest[message[ind]] = messagecode[head];

        if (lengthalphabet < message[ind]){
            lengthalphabet =  message[ind];
        }
    }
}

void ComputeLPSArray(int pattern[], int patternsize, int lpsarray[]){
    int suffixlength = 0;
    lpsarray[1] = 0;
    for (int ind = 2; ind <= patternsize; ++ind) {
        while (suffixlength > 0 && pattern[suffixlength + 1] != pattern[ind]) suffixlength = lpsarray[suffixlength];
        if (pattern[suffixlength + 1] == pattern[ind]) suffixlength++;
        lpsarray[ind] = suffixlength;
    }
}

int FindMatchingPosition(int source[], int destination[], int srclength, int destlength){
    int lpsarray[srclength];
    ComputeLPSArray(source, srclength, lpsarray);

    int lengthmatch = 0;
    for (int ind = 1; ind <= destlength; ++ind) {
        while (lengthmatch > 0 && source[lengthmatch + 1] != destination[ind]) lengthmatch = lpsarray[lengthmatch];
        if (source[lengthmatch + 1] == destination[ind]) ++lengthmatch;
        if (lengthmatch == srclength){
            return ind - srclength + 1;
        }
    }

    return -1;
}

int GetMatchingPosition(int source[], int destination[], int srclength, int destlength){
    pair<int, int> hs = GetHashes(source, srclength);
    int powhashes[2];
    int actualhashes[2] = { 0 };

    //std::cout << hs.first << " " << hs.second << "\n";

    powhashes[0] = Pow(kBase, srclength - 1, kHashKeys[0]);
    powhashes[1] = Pow(kBase, srclength - 1, kHashKeys[1]);

    for (int ind = 1; ind <= destlength; ++ind){
        actualhashes[0] = ((long long)actualhashes[0] * kBase + destination[ind]) % kHashKeys[0];
        actualhashes[1] = ((long long)actualhashes[1] * kBase + destination[ind]) % kHashKeys[1];

        if (ind >= srclength){
            //std::cout << actualhashes[0] << " " << actualhashes[1] << "\n";
           if (actualhashes[0] == hs.first && actualhashes[1] == hs.second){
               return ind - srclength + 1;
           }

           actualhashes[0] = (actualhashes[0] - (long long)destination[ind - srclength + 1] * powhashes[0]) % kHashKeys[0] + kHashKeys[0];
           actualhashes[1] = (actualhashes[1] - (long long)destination[ind - srclength + 1] * powhashes[1]) % kHashKeys[1] + kHashKeys[1];
        }
    }

    return -1;
}

int Pow(int number, int exponent, int modulo){
    long long output = 1;
    long long squarepow = number;

    while (exponent > 0){
        if (1 == (exponent & 1)){
            output = output * squarepow % modulo;
        }

        squarepow = squarepow * squarepow % modulo;

        exponent >>= 1;
    }

    return output;
}

pair<int, int> GetHashes(int source[], int srclength){
    int hashes[2] = { 0 };
    for (int index = 1; index <= srclength; ++index){
        hashes[0] = ((long long)hashes[0] * kBase + source[index]) % kHashKeys[0];
        hashes[1] = ((long long)hashes[1] * kBase + source[index]) % kHashKeys[1];
    }

    return make_pair(hashes[0], hashes[1]);
}

void ConcatArray(int array[], int arraysize){
    for (int index = 1; index <= arraysize; ++index){
        array[index + arraysize] = array[index];
    }
}

void SetDistaces(int source[], int destination[], int destsize){
    int lastappearences[kAlphabetSize] = { 0 };

    for (int index = 1; index <= destsize; ++index){
        lastappearences[source[index]] = index;
    }

    for (int index = 1; index <= destsize; ++index){
        if (lastappearences[source[index]] > index) {
            destination[index] = lastappearences[source[index]] - index;
        }else {
            destination[index] = destsize - index + lastappearences[source[index]];
        }

        lastappearences[source[index]] = index;
    }
}

void ReadInputData(){
    inputfile >> lengthofmessage >> lengthalphabet;
    for(int index = 1; index <= lengthofmessage; ++index) {
        inputfile >> message[index];
    }

    for (int index = 1; index <= lengthofmessage; ++index) {
        inputfile >> messagecode[index];
    }
}

void WriteOutputData(){
    //int numberofrightshifts = lengthofmessage + 1 - GetMatchingPosition(distmessagecode, distmessage, lengthofmessage, 2 * lengthofmessage);
    //int firstappearence = FindMatchingPosition(distmessagecode, distmessage, lengthofmessage, 2 * lengthofmessage);
    int numberofrightshifts = lengthofmessage + 1 - FindMatchingPosition(distmessagecode, distmessage, lengthofmessage, 2 * lengthofmessage);

    //std::cout << FindMatchingPosition(distmessagecode, distmessage, lengthofmessage, 2 * lengthofmessage) << "\n";
    //std::cout << GetMatchingPosition(distmessagecode, distmessage, lengthofmessage, 2 * lengthofmessage) << "\n";

    SetAlphabet(numberofrightshifts, lengthofmessage, alphabet);

    outputfile << numberofrightshifts << "\n";
    PrinteArray(alphabet, lengthalphabet);
}

void PrinteArray(int array[], int arraysize){
    for (int i = 1; i <= arraysize; ++i){
        outputfile << array[i] << " ";
    }
    outputfile << "\n";
}