Pagini recente » Cod sursa (job #2359622) | Cod sursa (job #2283919) | Cod sursa (job #2548230) | Cod sursa (job #1426152) | Cod sursa (job #2389820)
#include <fstream>
#include <iostream>
#include <cstring>
#include <cassert>
#include <vector>
#define MAX_LEN 2000000
int N, M;
char pattern[MAX_LEN + 2];
char str[MAX_LEN + 2];
int z[MAX_LEN + 1];
int size;
std::vector<int> matches;
int MAX(int X, int Y) {
return X > Y ? X : Y;
}
int MIN(int X, int Y) {
return X < Y ? X : Y;
}
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;
}
}
}
int computeMaxSuffix(char *needle, int len, int& period) {
int maxSuffix, j, k;
char a, b;
maxSuffix = -1;
j = 0;
k = period = 1;
while (j + k < len) {
a = needle[j + k];
b = needle[maxSuffix + k];
if (a < b) {
j += k;
k = 1;
period = j - maxSuffix;
} else if (a == b) {
if (k != period)
++k;
else {
j += period;
k = 1;
}
} else {
maxSuffix = j;
j = maxSuffix + 1;
k = period = 1;
}
}
return maxSuffix;
}
int choose(int lim) {
int i = 0;
while (i < size && z[i] < lim) {
i++;
}
if (i < size)
return z[i];
return z[size - 1];
}
int main(void) {
std::fstream in("strmatch.in");
in >> (pattern + 1) >> (str + 1);
M = strlen(pattern + 1);
N = strlen(str + 1);
Z(pattern + 1, M);
size = 0;
for (int i = 1; i < M; i++) {
if (z[i] + i == M) {
z[size++] = i;
}
}
if (!size || z[size - 1] != M)
z[size++] = M;
int period;
int x = computeMaxSuffix(pattern + 1, M, period);
//std::cout << "period = " << period << "\n";
assert(period == z[0]);
//std::cout << "x = " << x << "\n";
int sigma = 1;
int theta = 1 + x;
int ro = 0;
while (sigma <= N - M + 1) {
//std::cout << "sigma = " << sigma << " and thteta = " << theta << "\n";
while (theta < sigma + M && str[theta] == pattern[theta - sigma + 1]) {
theta++;
}
//std::cout << "nach While " << theta << " und Grenze " << (sigma + M) << "\n";
if (theta < sigma + M) {
theta++;
sigma = theta - x;
if (sigma < ro) {
//std::cout << "greater than " << (sigma - ro + M) << "so chosen " << choose(sigma - ro + M) << "\n";
sigma = ro - M + choose(sigma - ro + M);
}
if (sigma + x > theta)
theta = sigma + x;
} else {
//std::cout << "goes in\n";
int alfa = MAX(sigma, ro);
//std::cout << alfa << " mit " << sigma << " gegen " << (alfa - sigma + 1) << " mit length " << (sigma + x - alfa) << "\n";
if (sigma + x - alfa < 0)
matches.push_back(sigma);
else if (memcmp(str + alfa, pattern + (alfa - sigma + 1), sigma + x - alfa) == 0)
matches.push_back(sigma);
sigma += period;
ro = theta;
if (sigma + x > theta)
theta = sigma + x;
}
}
std::ofstream out("strmatch.out");
out << matches.size() << "\n";
for (int i = 0; i < matches.size(); i++)
out << (matches[i] - 1) << " ";
return 0;
}