題目:http://codeforces.com/problemset/problem/1016/B
題目大意:就是給兩個字符串s t,然後q次查詢,給出 [l, r], 問t出現的次數。
剛開始做這道題感覺就是瞎寫,沒有好好思考,下面給出官方的思路:首先看一下單純的做法。q次查詢,每次從 i 屬於 [l, r-m+1] 然後遍歷,看是否和t一樣。時間複雜度(q*m*n).
注意到t只能從s的n個位置開始,我們可以預處理t出現的位置,然後前綴和維護出現次數,這樣的話,每次查詢都是O(1).
AC代碼:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1000 + 7;
int pre[N];
int main() {
//freopen("in.txt", "r", stdin);
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
string s, t;
cin >> s >> t;
for(int i = 0; i < n - m + 1; i++) {//從s中找t開始的位置
bool flag = true;
for(int j = 0; j < m; j++) {
if(s[i + j] != t[j])
flag = false;
}
pre[i+1] = pre[i] + flag;//前綴和
}
for(int i = max(0, n - m + 1); i < n; i++)//上面終止條件,n-m+1 後面的pre還沒有值
pre[i+1] = pre[i];
for(int i = 0; i < q; i++) {
int l, r;
scanf("%d%d", &l, &r);
l--, r -= m - 1;//r -= m-1 變成起始位置(本次次數),l-- 變成上次出現次數
printf("%d\n", l <= r ? pre[r] - pre[l] : 0);
}
}