Pagini recente » Cod sursa (job #2952849) | Cod sursa (job #1274877) | Rezultate Info Oltenia 2019 Proba pe Echipe | Cod sursa (job #2908090) | Cod sursa (job #2445920)
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
//---------------------------------------------------------------------------
// HyperKMP
// (c) 2019 Stoian Mihail
// - compress the pi-table to get rid of the worst-case of KMP
//---------------------------------------------------------------------------
using namespace std;
//---------------------------------------------------------------------------
#define MAX_N 2000000
#define MAX_COUNT 1000
//---------------------------------------------------------------------------
unsigned length, countMatches;
char buffer[2 * MAX_N + 5];
unsigned matches[MAX_COUNT + 1];
//---------------------------------------------------------------------------
unsigned psi[MAX_N + 2];
void compressPi()
// compress pi[] and create two new arrays: psi[] and omega[]
// description in README
{
// Initialize the first values
// 0 is the first state. At this step it receives 2 sons
psi[0] = 0;
psi[1] = 0;
// Compute pi and psi
unsigned k = 0, q = 1;
const char* pattern = buffer;
for (; pattern[q] != '\n'; ++q) {
// Compute psi
while ((k > 0) && (pattern[q] != pattern[k])) {
k = psi[k];
}
if (pattern[q] == pattern[k]) {
k++;
}
// Compress possible path
// For understandability reasons, keep the formula like this
psi[q + 1] = (pattern[q + 1] == pattern[k]) ? psi[k] : k;
}
length = q;
}
//---------------------------------------------------------------------------
void search()
// checks if the pattern can be found in str
{
if (length == 1) {
cerr << "Not supported by now" << endl;
exit(0);
}
const char* str = buffer + length + 1;
const char* pattern = buffer;
char firstChar = pattern[0];
unsigned q = 0; // current state
unsigned index = 0;
hyperKMPSearch : {
if (str[index] == '\0')
return;
// Doesn't enter in the while anyhow
if (!q) {
const char* found = strchr(str + index, firstChar);
if (!found)
return;
// Set the new state
q = 1;
index = found - str + 1;
goto hyperKMPSearch;
}
// Now we have at least the first q chars matched
// Get rid of 2 comparisons when the char matches
if (str[index] != pattern[q]) {
q = psi[q];
while ((q > 0) && (str[index] != pattern[q]))
q = psi[q];
// TODO: what happens when q == 0?
if (str[index] == pattern[q])
++q;
} else {
++q;
}
// Found?
if (q == length) {
if ((++countMatches) <= MAX_COUNT) {
matches[countMatches - 1] = index - length + 1;
}
}
++index;
goto hyperKMPSearch;
}
}
//---------------------------------------------------------------------------
int main(int argv, char** argc) {
FILE *in;
#if 0
in = fopen(argc[1], "r");
#else
in = fopen("strmatch.in", "r");
#endif
size_t essen = fread(buffer, 1, 2 * MAX_N + 5, in);
fclose(in);
compressPi();
search();
std::ofstream out("strmatch.out");
out << countMatches << endl;
unsigned lim = (countMatches < MAX_COUNT) ? countMatches : MAX_COUNT;
for (unsigned index = 0; index < lim; ++index)
out << matches[index] << " ";
out << endl;
out.close();
return 0;
}