/* * 方針: * 1. 参照テキストの suffix array を作成する。[Manber and Myers 1993] の * アルゴリズムによる。 * (Larsson Sadakane 法の説明の前半) などが分かりやすいかも。コード長 * 短縮のため、本来の radix sort の代わりに STL の sort を利用。 * (→ 時間複雑度は O(n (log n)^2)) * 2. 各クエリについて、当該文字列で始まる suffix の範囲を二分探索で求める。 */ #include #include #include #include #include using namespace std; struct GroupLess { const int h; const vector &s2g; GroupLess(int h, const vector &s2g) : h(h), s2g(s2g) {} bool operator()(int s1, int s2) const { const int a = s1 + h, b = s2 + h; return (a < s2g.size() && b < s2g.size()) ? (s2g[a] < s2g[b]) : (b < s2g.size()); } }; vector make_suffix_array(const string &str) { const int N = str.length(); vector i2s(N), s2g(N); // (i 番目にどの suffix がいるか), (各 suffix がどのグループに属しているか) for (int i = 0; i < N; i++) s2g[i2s[i] = i] = str[i]; for (int h = 1; ; h *= 2) { const vector old_s2g(s2g); const GroupLess less(h/2, old_s2g); bool done = true; for (int i = 0; i < N; i++) { const int last = (h == 1 ? N-1 : s2g[i2s[i]]); if (last != i) { sort(i2s.begin()+i, i2s.begin()+last+1, less); for (int j = last, g; j >= i; j--) { if (j == last || less(i2s[j], i2s[j+1])) g = j; s2g[i2s[j]] = g; } i = last; done = false; } } if (done) break; } return i2s; } typedef enum { LOWER_BOUND, UPPER_BOUND } SearchType; int binary_search(const string &text, const vector &sarray, const string &key, SearchType type) { int low = -1, high = text.length(); while (low+1 != high) { int mid = (low + high) / 2; const string &m = text.substr(sarray[mid], key.length()); if ((type == LOWER_BOUND && key > m) || (type == UPPER_BOUND && key >= m)) low = mid; else high = mid; } return high; } int main() { for (int t = 1; ; t++) { ostringstream out; string line; if (getline(cin, line), line != "%%%%%") break; while (getline(cin, line), line != "%%%%%") out << line << ' '; const string &text = out.str(); const vector &sarray = make_suffix_array(text); if (t > 1) cout << endl; cout << "Case " << t << ":" << endl; while (getline(cin, line), line != "%%%%%") cout << (binary_search(text, sarray, line, UPPER_BOUND) - binary_search(text, sarray, line, LOWER_BOUND)) << endl; getline(cin, line); } return 0; }