Pagini recente » Cod sursa (job #271255) | Cod sursa (job #2922813) | Cod sursa (job #2497152) | Cod sursa (job #1903799) | Cod sursa (job #1560424)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
class SufA {
public:
const string s;
const int n;
vector<int> sa;
vector<int> elcp;
public:
SufA(const string& _s) : s(_s), n(s.size()) {
}
template <typename T>
void sais(const int n, const T& s, const int nc) {
const int nil = -1;
fill(begin(sa), begin(sa)+n, nil);
vector<bool> t(n);
t[n-1] = true;
for (int i = n-2; i >= 0; i--) {
t[i] = s[i] < s[i+1]
|| s[i] == s[i+1] && t[i+1];
}
auto isLMS = [&t] (int i) {
return t[i] && i >= 1 && !t[i-1];
};
vector<int> bkt(nc+1);
for (int i = 0; i < n; i++) {
bkt[s[i]+1]++;
}
partial_sum(begin(bkt), end(bkt), begin(bkt));
auto bkt1 = bkt;
for (int i = n-1; i >= 1; i--) {
if (isLMS(i)) {
sa[--bkt1[s[i]+1]] = i;
}
}
auto induceSAl = [&] (vector<int> bkt) {
for (int i = 0; i < n-1; i++) {
int j = sa[i]-1;
if (j >= 0 && !t[j]) {
sa[bkt[s[j]]++] = j;
}
}
};
auto induceSAs = [&] (vector<int> bkt) {
for (int i = n-1; i >= 2; i--) {
int j = sa[i]-1;
if (j >= 0 && t[j]) {
sa[--bkt[s[j]+1]] = j;
}
}
};
induceSAl(bkt);
induceSAs(bkt);
int n1 = 0;
for (int i = 0; i < n; i++) {
if (isLMS(sa[i])) {
sa[n1++] = sa[i];
}
}
int ord = 0;
for (int i = 0; i < n1; i++) {
if (i >= 1) {
ord++;
for (int j = 0; s[sa[i-1]+j] == s[sa[i]+j]; j++) {
if (isLMS(sa[i]+j) && j >= 1) {
if (isLMS(sa[i-1]+j)) ord--;
break;
}
}
}
sa[n1+sa[i]/2] = ~ord;
}
if (ord+1 < n1) {
int* s1 = &sa[0]+n1;
for (int i = n1, j = 0; j < n1; i++) {
if (sa[i] < 0) {
s1[j++] = ~sa[i];
}
}
sais(n1, s1, ord+1);
for (int i = 1, j = 0; i < n; i++) {
if (isLMS(i)) {
s1[j++] = i;
}
}
for (int i = 0; i < n1; i++) {
sa[i] = s1[sa[i]];
}
}
fill(begin(sa)+n1, begin(sa)+n, nil);
bkt1 = bkt;
for (int i = n1-1; i >= 0; i--) {
int j = sa[i];
sa[i] = nil;
sa[--bkt1[s[j]+1]] = j;
}
induceSAl(bkt);
induceSAs(bkt);
}
void buildsa() {
sa.resize(n);
if (n >= 2) sais(n, s, 128);
// for (int i = 0; i < n; i++) {
// printf("%d%c", sa[i], " \n"[i == n-1]);
// }
}
void buildelcp() {
vector<int> ra(n);
for (int i = 0; i < n; i++) {
ra[sa[i]] = i;
}
elcp.resize(2*n);
// elcp[2*n-1] = -1;
for (int j = 0, len = 0; j < n-1; j++) {
int i = sa[ra[j]-1];
while (s[i+len] == s[j+len]) len++;
elcp[n+ra[i]] = len;
len = max(len-1, 0);
}
for (int i = n-1; i >= 1; i--) {
elcp[i] = min(elcp[2*i], elcp[2*i+1]);
}
// int x = n;
// while (x % 2 == 0) x /= 2;
// x /= 2;
// while (x != 0) {
// elcp[x] = -1;
// x /= 2;
// }
// for (int i = 0; i < 2*n; i++) {
// printf("%d%c", elcp[i], " \n"[i == 2*n-1]);
// }
}
pair<int,int> range(const string& t) {
int l = n;
int i = n>>__builtin_ctz(n);
int cp = 0;
bool lr = false;
while (l+l/i >= 2*n) {
i <<= 1;
}
while (i <= l) {
// if (t == "unu") {
// printf("%d %d\n", i, l);
// }
bool next;
if (elcp[i+lr] != cp) {
next = lr == elcp[i+lr] < cp;
} else {
int k = sa[l-n+l/i];
while (cp < t.size() && t[cp] == s[k+cp]) cp++;
if (cp == t.size()) {
l = l+l/i;
i++;
i <<= 1;
break;
}
next = s[k+cp] < t[cp];
lr = !next;
}
if (next) {
l += l/i;
i++;
if (i&1) {
i <<= 1;
} else {
i >>= __builtin_ctz(i);
}
while (l+l/i >= 2*n) {
i <<= 1;
}
} else {
i <<= 1;
}
}
if (cp < t.size()) {
// printf("%d %d %d\n", n, i, l);
int k = l-n+1;
return {k, k};
}
int r = l;
while (i <= l) {
if (elcp[i-1] < t.size()) {
i <<= 1;
} else {
l -= l/i;
i--;
i <<= 1;
}
}
l -= n;
i = r>>__builtin_ctz(r);
while (r+r/i >= 2*n) {
i <<= 1;
}
while (i <= r) {
if (elcp[i] < t.size()) {
i <<= 1;
} else {
r += r/i;
i++;
if (i&1) {
i <<= 1;
} else {
i >>= __builtin_ctz(i);
}
while (r+r/i >= 2*n) {
i <<= 1;
}
}
}
r -= n-1;
return {l, r};
}
};
int main() {
ios::sync_with_stdio(false);
freopen("ahocorasick.in", "r", stdin);
freopen("ahocorasick.out", "w", stdout);
string s;
cin >> s;
SufA suf(s+'\0');
suf.buildsa();
suf.buildelcp();
int nq;
cin >> nq;
for (int iq = 0; iq < nq; iq++) {
string t;
cin >> t;
auto res = suf.range(t);
// printf("%d %d\n", res.first, res.second);
printf("%d\n", res.second-res.first);
}
}