The code below is for: http://hihocoder.com/problemset/solution/237010
With enough comments to understand:
#include <cmath> #include <cstdio> #include <vector> #include <string> #include <iostream> #include <algorithm> #include <unordered_map> using namespace std; int kmp_cnt(const string &tgt, const string &pt) { size_t lent = tgt.length(); size_t lenp = pt.length(); if (lenp > lent || lenp == 0) return 0; // Pass 1 vector<int> matched(lenp + 1, 0); // in terms of length, as j // i: inx on target, j: matched count on pattern int j = 0; for(int i = 1; i < lenp; i ++) { // j > 0 below is to avoid deadloop when matched[j] is 0 too while (j > 0 && pt[j] != pt[i]) j = matched[j]; // matching? inc counter if (pt[j] == pt[i]) j ++; // update jump table - number of chars matched matched[i + 1] = j; } // Pass 2 int ret = 0; for (int i = 0, j = 0; i < lent; i ++) { while (j > 0 && tgt[i] != pt[j]) j = matched[j]; if (tgt[i] == pt[j]) j ++; if (j == lenp) { ret ++; } } return ret; } int main() { int t; cin >> t; string tmp; getline(cin, tmp); // consume the newline from above while (t--) { string sp; getline(cin, sp); string st; getline(cin, st); int ret = kmp_cnt(st, sp); cout << ret << endl; } return 0; }