Cod sursa(job #1184397)

Utilizator howsiweiHow Si Wei howsiwei Data 12 mai 2014 15:57:50
Problema Aho-Corasick Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.06 kb
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

int n;
string s;
vector<int> sa;
vector<int> rank;
vector<int> lcp;
vector<int> llcp;
vector<int> rlcp;

bool cmp(int x, int y)
{
	return s[x] < s[y];
}

void buildsa()
{
	sa.resize(n);
	rank.resize(n);
	for (int i = 0; i < n; i++) {
		sa[i] = i;
	}
	sort(sa.begin(), sa.end(), cmp);
	vector<int> oldsa(n);
	vector<int> oldrank(n);
	vector<int> pos(n+1);
	for (int len = 1; ; len *= 2) {
		int cnt = 0;
		swap(rank, oldrank);
		for (int i = 0; i < n; i++) {
			int x = sa[i];
			bool eq;
			if (i == 0) {
				eq = false;
			}
			else {
				int w = sa[i-1];
				if (len == 1) {
					eq = s[w] == s[x];
				}
				else {
					// assume that s[n-1] is different from s[i] for i in 0..n-2
					eq = oldrank[w] == oldrank[x] && oldrank[w+len/2] == oldrank[x+len/2];
				}
			}
			if (eq) {
				pos[cnt]++;
			}
			else {
				pos[++cnt] = 1;
			}
			rank[x] = cnt-1;
		}
		if (cnt == n) {
			break;
		}
		pos[0] = 0;
		for (int i = 1; i <= cnt; i++) {
			pos[i] += pos[i-1];
		}
		swap(sa, oldsa);
		for (int i = n-len; i < n; i++) {
			sa[pos[rank[i]]++] = i;
		}
		for (int i = 0; i < n; i++) {
			int x = oldsa[i]-len;
			if (x >= 0) {
				sa[pos[rank[x]]++] = x;
			}
		}
	}
}

void buildlcp()
{
	lcp.resize(n);
	// assume that sa[0] = n-1
	for (int i = 0, len = 0; i < n-1; i++) {
		int h = sa[rank[i]-1];
		// assume that s[n-1] is different from s[i] for i in 0..n-2
		while (s[h+len] == s[i+len]) {
			len++;
		}
		lcp[rank[i]] = len;
		if (len > 0) {
			len--;
		}
	}
}

void buildllcp()
{
	llcp.assign(lcp.begin(), lcp.end());
	for (int stp = 2; stp < n; stp *= 2) {
		for (int i = stp; i < n; i += stp) {
			llcp[i] = min(llcp[i], llcp[i-stp/2]);
		}
	}
}

void buildrlcp()
{
	rlcp.assign(lcp.begin()+1, lcp.end());
	rlcp.push_back(0);
	for (int stp = 2; stp < n; stp *= 2) {
		for (int i = 0; i < n; i += stp) {
			rlcp[i] = i+stp >= n ? 0 : min(rlcp[i], rlcp[i+stp/2]);
		}
	}
}

int count(const string & t)
{
	int stp = 1;
	while (stp*2 < n) {
		stp *= 2;
	}
	// assume that length of lcp of t and s[sa[0]] is 0
	int lo = 0;
	for (int w = 0, y = 0; stp; stp /= 2) {
		int mi = lo+stp;
		if (mi >= n) {
			y = 0;
			continue;
		}
		int x;
		bool b;
		if (w < y) {
			x = min(y, rlcp[mi]);
			b = y == rlcp[mi];
		}
		else {
			x = min(w, llcp[mi]);
			b = w == llcp[mi];
		}
		if (b) {
			int m = t.size();
			while (x < m && s[sa[mi]+x] == t[x]) {
				x++;
			}
			if (x == m) {
				int lo = mi, up = mi;
				do {
					if (rlcp[lo-stp] >= m) {
						lo -= stp;
					}
					if (up+stp < n && llcp[up+stp] >= m) {
						up += stp;
					}
					stp /= 2;
				} while (stp);
				return up+1-lo;
			}
		}
		if (s[sa[mi]+x] < t[x]) {
			lo = mi;
			w = x;
		}
		else {
			y = x;
		}
	}
	return 0;
}

int main()
{
	freopen("ahocorasick.in", "r", stdin);
	freopen("ahocorasick.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin >> s;
	s += '\0';
	n = s.size();
	buildsa();
	buildlcp();
	buildllcp();
	buildrlcp();
	int m;
	cin >> m;
	for (int i = 0; i < m; i++) {
		string t;
		cin >> t;
		printf("%d\n", count(t));
	}
	return 0;
}