Pagini recente » Cod sursa (job #2515016) | Cod sursa (job #2603275) | Cod sursa (job #2822722) | Cod sursa (job #2075709) | Cod sursa (job #1571165)
#include <fstream>
#include <array>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <limits>
using std::string;
using std::vector;
using std::pair;
using std::array;
const int NMAX = 2000011;
const int NUM_OF_MAX_MATCHES_TO_SHOW = 1000;
using BadCharTable = array<vector<int>, std::numeric_limits<char>::max()>;
vector<int> buildSuffixTable(const string& P) {
vector<int> Z;
const string rP (P.rbegin(), P.rend());
Z.resize(P.size());
Z[0] = rP.size();
for (int k = 1, lt = 0, rt = 0; k < rP.size(); ++k) {
if (k > rt) {
int i;
for (i = 0; i + k < rP.size() && rP[i] == rP[i + k]; ++i);
Z[k] = i;
if (i) {
lt = k;
rt = i + k - 1;
}
}
else {
if (Z[k - lt] < rt - k + 1) {
Z[k] = Z[k - lt];
}
else {
int i;
for (i = rt + 1; i < rP.size() && rP[i] == rP[i - k]; ++i);
Z[k] = i - k;
lt = k;
rt = i - 1;
}
}
}
std::reverse(Z.begin(), Z.end());
return Z;
}
BadCharTable buildBadCharTable(const string& P) {
BadCharTable t;
for (size_t i = 0; i < P.size(); ++i) {
t[P[i]].push_back(i);
}
return t;
}
int computeBadCharShift(const pair<char, int>& x, const BadCharTable& t) {
const auto& v = t[x.first];
if (v.empty()) {
return x.second;
}
else if (v.size() <= 15) {
for (int i = v.size() - 1; i >= 0; --i) {
if (v[i] < x.second) {
return x.second - v[i];
}
}
return x.second;
}
else {
auto it = std::lower_bound(v.begin(), v.end(), x.second);
return x.second - (it == v.begin() ? 0 : *(it - 1));
}
}
pair<int, vector<int>> strMatch(const string& P, const string& T) {
if (P.size() > T.size()) {
return std::make_pair(0, vector<int>{});
}
else if (P.size() == T.size()) {
return P != T ? std::make_pair(0, vector<int>{}) : std::make_pair(1, vector<int>{0});
}
vector<int> L, l;
vector<int> N = buildSuffixTable(P);
BadCharTable badCharTable = buildBadCharTable(P);
L.resize(P.size() + 2);
l.resize(P.size() + 2);
for (size_t i = 0; i < P.size() - 1; ++i) {
int j = P.size() - N[i];
if (j < P.size()) {
L[j] = i + 1;
}
}
for (size_t i = 0; i < P.size(); ++i) {
if (N[i] == i+1) {
l[P.size() - i - 1] = i + 1;
}
}
for (int i = P.size() - 2; i >= 0; --i) {
if (0 == l[i]) {
l[i] = l[i + 1];
}
}
int numMatches = 0, skip = 0;
vector<int> matches;
matches.reserve(NUM_OF_MAX_MATCHES_TO_SHOW);
for (size_t i = P.size() - 1; i < T.size(); i += skip) {
int k = i, j = P.size() - 1;
for (; j >= 0 && T[k] == P[j]; --k, --j);
if (j < 0) {
skip = P.size() - l[1];
++numMatches;
if (numMatches <= matches.capacity()) {
matches.push_back(k + 1);
}
}
else {
skip = std::max(1, computeBadCharShift({T[i], j}, badCharTable));
if (j == P.size() - 1) {
}
else if (L[j + 1] > 0) {
skip = std::max<int>(skip, P.size() - L[j + 1]);
}
else {
skip = std::max<int>(skip, P.size() - l[j + 1]);
}
}
}
return std::make_pair(numMatches, matches);
}
int main() {
string P, T;
std::ifstream in{"strmatch.in"};
std::ofstream out{"strmatch.out"};
in >> P >> T;
const auto x = strMatch(P, T);
out << x.first << '\n';
std::copy(x.second.begin(), x.second.end(), std::ostream_iterator<int>{out, " "});
return 0;
}