Pagini recente » Cod sursa (job #2641349) | Cod sursa (job #372197) | Cod sursa (job #710904) | Cod sursa (job #1980698) | Cod sursa (job #2395152)
#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;
}
}
int choose(int val) {
while (remained < size && z[remained] < val)
remained++;
if (remained < size) {
//cerr << "voitai " << val << " ti-am dat " << z[remained] << endl;
return z[remained];
} else {
return z[size - 1];
}
}
vector<int> twoWaySearch(char* haystack, int haystacklen, char* needle, int needlelen) {
int maxSuffix, period;
preparePattern(needle, needlelen, maxSuffix, period);
cerr << "prepare liefert " << maxSuffix << " " << period << endl;
int sigma = 0;
int theta = 1 + maxSuffix;
int lastMatch = 0;
vector<int> matches;
remained = 0;
while (sigma <= haystacklen - needlelen) {
while (theta < sigma + needlelen && haystack[theta] == needle[theta - sigma]) {
theta++;
}
if (theta < sigma + needlelen) {
sigma = theta - maxSuffix;
theta++;
if (sigma < lastMatch) {
assert(0);
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;
}
}
return matches;
}
int main(void) {
ifstream in("strmatch.in");
ofstream out("strmatch.out");
in >> pattern >> text;
int M = strlen(pattern);
int N = strlen(text);
Z(pattern, M);
for (int i = 1; i < M; i++) {
if (z[i] + i == M) {
z[size++] = i;
}
}
z[size++] = M;
cerr << "Periods\n";
for (int i = 0; i < size; i++) {
cerr << z[i] << " ";
}
vector<int> matches = twoWaySearch(text, N, pattern, M);
out << matches.size() << endl;
for (int i = 0; i < matches.size() && i < 1000; i++)
out << matches[i] << " ";
return 0;
}