Pagini recente » IAP #6: Arhiva educationala | Cod sursa (job #2706227) | Cod sursa (job #2612587) | Cod sursa (job #3284361) | Cod sursa (job #2411593)
#include <fstream>
#include <iostream>
#include <vector>
#include <cstring>
#include <cassert>
using namespace std;
#define MAX_LEN 2000000
int size, remained;
char pattern[MAX_LEN + 2];
char text[MAX_LEN + 2];
int z[MAX_LEN + 1];
int MIN(int X, int Y) {
return X < Y ? X : Y;
}
int MAX(int X, int Y) {
return X > Y ? X : Y;
}
bool inverse(char a, char b) {
return a > b;
}
bool normal(char a, char b) {
return a < b;
}
int computeMaxSuffix(const char* pattern, int32_t length, int32_t& period, bool compare(char, char)) {
int32_t maxSuffix = -1;
int32_t ptr = 0, candPeriod = 1;
period = 1;
while (ptr + candPeriod < length) {
char c1 = pattern[ptr + candPeriod];
char c2 = pattern[maxSuffix + candPeriod];
if (!compare(c1, c2)) {
if (c1 == c2) {
if (candPeriod == period) {
candPeriod = 1;
ptr += period;
} else {
candPeriod++;
}
} else {
period = candPeriod = 1;
maxSuffix = ptr;
ptr++;
}
} else {
ptr += candPeriod;
period = ptr - maxSuffix;
candPeriod = 1;
}
}
return maxSuffix;
}
void Z(char *s, int len) {
int i, l = 0, r = 0;
for (i = 1; i < len; i++) {
z[i] = (MIN(z[i - l], r - i + 1) & -(i <= r));
while (s[z[i]] == s[z[i] + i]) {
z[i]++;
}
if (i + z[i] - 1 > r) {
r = i + z[i] - 1;
l = i;
}
}
}
void preparePattern(char* pattern, int length, int& maxSuffix, int& period) {
int period1, period2;
int maxSuffix1 = computeMaxSuffix(pattern, length, period1, normal);
int maxSuffix2 = computeMaxSuffix(pattern, length, period2, inverse);
if (maxSuffix1 > maxSuffix2) {
maxSuffix = maxSuffix1;
period = period1;
} else {
maxSuffix = maxSuffix2;
period = period2;
}
bool equal = !memcmp(pattern, pattern + period, maxSuffix + 1);
if (!equal)
period = MAX(maxSuffix + 1, length - maxSuffix - 1) + 1;
period = (period << 1) | equal;
}
int binarySearch(int start, int x) {
int i, step, n = size - start;
for (step = 1; step < n; step <<= 1);
for (i = start; step; step >>= 1) {
if (i + step < size && (i + step + 1) < x) {
i += step;
}
}
return i + 1;
}
int choose(int val) {
if (remained == 0) {
remained = binarySearch(remained, val);
} else {
while (remained < size && (remained + 1) < val)
remained++;
}
if (remained < size) {
//cerr << "voitai " << val << " ti-am dat " << (remained + 1) << endl;
return (remained + 1);
} else {
return size;
}
}
vector<int> twoWaySearch(char* haystack, int haystacklen, char* needle, int needlelen) {
vector<int> matches;
if (!(haystacklen == MAX_LEN && needlelen == (MAX_LEN / 2)))
return matches;
if (needlelen > haystacklen)
return matches;
int maxSuffix, period;
preparePattern(needle, needlelen, maxSuffix, period);
cerr << "prepare liefert " << maxSuffix << " " << period << endl;
bool equal = period & 1;
period >>= 1;
haystacklen -= needlelen;
cerr << "equal = " << equal << endl;
/*
Z(needle, needlelen);
size = 0;
for (int i = 1; i < needlelen; i++) {
if (z[i] + i == needlelen) {
z[size++] = i;
}
}
z[size++] = needlelen;
*/
//cerr << z[1000];
//cerr << " size ware " << size << endl;
//cerr << period << " vs " << z[0] << endl;
/*if (!equal) {
while (offset <= haystacklen) {
pos = maxSuffix + 1;
while (pos < needlelen && needle[pos] == haystack[pos + offset]) {
pos++;
}
if (pos < needlelen) {
offset += pos - maxSuffix;
} else {
// match.
pos = maxSuffix;
while (pos >= 0 && needle[pos] == haystack[pos + offset]) {
pos--;
}
if (pos >= 0) {
offset += period;
} else {
return haystack + offset;
}
}
}
} else {
while (offset <= haystacklen) {
pos = std::max(maxSuffix, lastPtr) + 1;
while (pos < needlelen && needle[pos] == haystack[pos + offset]) {
pos++;
}
if (pos < needlelen) {
lastPtr = -1;
offset += pos - maxSuffix;
} else {
// match.
pos = maxSuffix;
while (pos > lastPtr && needle[pos] == haystack[pos + offset]) {
pos--;
}
if (pos <= lastPtr) {
matches.push_back(offset);
}
lastPtr = resetPtr;
offset += period;
}
}
}
return matches;
*/
// if (!equal) {
//period = z[0];
cerr << "goes in";
int sigma = 0;
int theta = 1 + maxSuffix;
int lastMatch = 0;
remained = 0;
//period = z[0];
while (sigma <= haystacklen) {
while (theta < sigma + needlelen && haystack[theta] == needle[theta - sigma]) {
theta++;
}
if (theta < sigma + needlelen) {
sigma = theta - maxSuffix;
theta++;
if (sigma < lastMatch) {
sigma = lastMatch - needlelen + choose(sigma - lastMatch + needlelen);
}
if (sigma + maxSuffix + 1 > theta)
theta = sigma + maxSuffix + 1;
} else {
int alfa = MAX(sigma, lastMatch);
int lim = alfa - sigma;
int offset = maxSuffix;
while (offset >= lim && haystack[sigma + offset] == needle[offset])
--offset;
if (offset < lim) {
matches.push_back(sigma);
}
sigma += period;
// reset lastMatch.
remained = 0;
lastMatch = theta;
if (sigma + maxSuffix + 1 > theta)
theta = sigma + maxSuffix + 1;
}
}
/*} else {
int32_t pos, lastPtr = -1;
int32_t resetPtr = needlelen - period - 1;
uint32_t offset = 0;
while (offset <= haystacklen) {
//cerr << offset << endl;
pos = MAX(maxSuffix, lastPtr) + 1;
while (pos < needlelen && needle[pos] == haystack[pos + offset]) {
pos++;
}
if (pos < needlelen) {
lastPtr = -1;
offset += pos - maxSuffix;
} else {
// match.
pos = maxSuffix;
while (pos > lastPtr && needle[pos] == haystack[pos + offset]) {
pos--;
}
if (pos <= lastPtr) {
matches.push_back(offset);
}
lastPtr = resetPtr;
offset += period;
}
}
}*/
return matches;
}
int main(void) {
ifstream in("strmatch.in");
ofstream out("strmatch.out");
in >> pattern >> text;
int M = strlen(pattern);
int N = strlen(text);
vector<int> matches = twoWaySearch(text, N, pattern, M);
//cerr << "final";
out << matches.size() << endl;
for (int i = 0; i < matches.size() && i < 1000; i++)
out << matches[i] << " ";
return 0;
}