#include #include #include #include #include #include using namespace std; // implementation of suffix array construction based on skew algorithm struct Index { typedef unsigned long long Int; static const Int MAX = 200000; //------------------------------------------------------------------- // zero-free out_of_range-torrerent arrays //------------------------------------------------------------------- struct Array : vector { Int& operator[](size_t i) { return vector::operator[](i); } const Int operator[](size_t i) const { return size()<=i ? 0 : vector::operator[](i); } }; //------------------------------------------------------------------- // [cab] ==> [312] : "cab$ is the 3rd suffix", "ab$ is the 1st" ... //------------------------------------------------------------------- static void suffix_ranking( const Array& v, Array* pResult ) { pResult->resize( v.size() ); Array sary; suffix_array( v, &sary ); for(size_t i=0; i!=sary.size(); ++i) (*pResult)[sary[i]-1] = i+1; #ifdef EBUG cerr<< "v : "; for(size_t i=0; i!=v.size(); ++i) cerr << v[i] << " "; cerr << endl; cerr<< "sary: "; for(size_t i=0; i!=v.size(); ++i) cerr << sary[i] << " "; cerr << endl; cerr<< "rank: "; for(size_t i=0; i!=v.size(); ++i) cerr << (*pResult)[i] << " "; cerr << endl; #endif } //------------------------------------------------------------------- // [cab] ==> [231] : "suffix at pos2 (ab$) is the first suffix", ... //------------------------------------------------------------------- static void suffix_array( const Array& v, Array* pResult ) { pResult->resize( v.size(), 1 ); // Small cases if( v.size() <= 1 ) {return;} if( v.size() == 2 ) {(*pResult)[(v[0]>=v[1] ? 0 : 1)] = 2; return;} // STEP1 // make mod1/mod2 triples and recursively their suffix ranks Array triple_rank; { map idx; { set triples; for(size_t i=1; i<=v.size(); i+=3) triples.insert( v[i]*MAX*MAX+v[i+1]*MAX+v[i+2] ); for(size_t i=2; i::iterator it=triples.begin(); it!=triples.end(); ++it) idx[*it] = ++r; } Array triple_array; { for(size_t i=1; i<=v.size(); i+=3) triple_array.push_back( idx[v[i]*MAX*MAX+v[i+1]*MAX+v[i+2]] ); for(size_t i=2; ibegin(), pResult->end(), cmp(&v, &triple_rank) ); } struct cmp { const Array *pv, *ptr; cmp( const Array* pv, const Array* ptr ) : pv(pv), ptr(ptr) {} Int v(Int i) const {return (*pv)[i];} Int tr(Int i) const {return (*ptr)[i%3==1 ? i/3 : (pv->size()+2)/3+i/3];} bool operator()( Int i, Int j ) const { --i, --j; if( v(i)!=v(j) ) return v(i) < v(j); if( v(i+1)!=v(j+1) ) return v(i+1) < v(j+1); if( i%3!=0 && j%3!=0 ) return tr(i) < tr(j); // 11, 12, 21, 22 if( i%3!=2 && j%3!=2 ) return tr(i+1) < tr(j+1); // 00, 01, 10 return tr(i+2) < tr(j+2); // 02, 20 } }; //------------------------------------------------------------------- // MAIN //------------------------------------------------------------------- Index( const char* p, int N ) { Array v, sary0; for(size_t i=0; i!=N; ++i) v.push_back( (unsigned char)(p[i]) ); suffix_array( v, &sary0 ); for(size_t i=0; i!=N; ++i) sary.push_back( p+sary0[i]-1 ); #ifdef EBUG for(int i=0; i!=sary.size(); ++i) cerr << sary[i] << "$" << endl; #endif } int count( string& q ) { vector::iterator b = lower_bound( sary.begin(), sary.end(), q.c_str(), str_cmp() ); q[q.size()-1]++; vector::iterator e = lower_bound( b, sary.end(), q.c_str(), str_cmp() ); return e-b; } struct str_cmp { bool operator()( const char* p, const char* q ) const { return strcmp(p,q)<0; }}; vector sary; }; int main() { int N=0; for(string str; getline(cin,str);) { if(N++) cout << endl; cout << "Case " << N << ":" << endl; // reference text string text; while( getline(cin,str), str!="%%%%%" ) text+=str, text+=" "; // indexing Index idx(text.c_str(), text.size()); // query while( getline(cin,str), str!="%%%%%" ) cout << idx.count(str) << endl; getline(cin,str); } }