Problem p00317 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> T;

const int mod1 = 1000000007;
const int base1 = 1009;

const int mod2 = 1000000007;
const int base2 = 1007;

int N, M;
char s[100000][201];
char d[100000][201];
int ans[100000];
bool rev[100000];
map<pair<int, int>, int> hash1[200];
set<pair<int, int>> endd[200];

T connect(T &hash, char c) {
  return (make_pair(1LL * (hash.first + c) * base1 % mod1,
                    1LL * (hash.second + c) * base2 % mod2));
}

int countStrings(int p, int idx, T val) {
  if (d[p][idx] == '\0') {
    return (endd[idx - 1].find(val) != endd[idx - 1].end());
  } else if (d[p][idx] == '*') {
    return (hash1[idx - 1].find(val) != hash1[idx - 1].end()
                ? hash1[idx - 1][val]
                : 0);
  } else if (d[p][idx] == '?') {
    int ret = 0;
    for (char c = 'a'; c <= 'z'; c++) {
      ret += countStrings(p, idx + 1, connect(val, c));
    }
    return (ret);
  } else {
    return (countStrings(p, idx + 1, connect(val, d[p][idx])));
  }
}

int main() {
  scanf("%d %d", &N, &M);
  for (int i = 0; i < N; i++) {
    scanf(" %s", s[i]);
  }
  for (int i = 0; i < M; i++) {
    scanf(" %s", d[i]);
    if (d[i][0] == '*') {
      reverse(d[i], d[i] + strlen(d[i]));
      rev[i] = true;
    }
  }

  const int BACKET = 500;
  for (int i = 0; i < N; i += BACKET) {
    for (int j = 0; j < 200; j++) {
      hash1[j].clear();
      endd[j].clear();
    }
    for (int k = i; k < min(N, i + BACKET); k++) {
      int len = strlen(s[k]);
      T val = {0, 0};
      for (int j = 0; j < len; j++) {
        val = connect(val, s[k][j]);
        hash1[j][val]++;
      }
      endd[len - 1].insert(val);
    }
    for (int j = 0; j < M; j++) {
      if (!rev[j])
        ans[j] += countStrings(j, 0, {0, 0});
    }
  }

  for (int i = 0; i < N; i++) {
    reverse(s[i], s[i] + strlen(s[i]));
  }

  for (int i = 0; i < N; i += BACKET) {
    for (int j = 0; j < 200; j++) {
      hash1[j].clear();
    }
    for (int k = i; k < min(N, i + BACKET); k++) {
      T val(0, 0);
      int len = strlen(s[k]);
      for (int j = 0; j < len; j++) {
        val = connect(val, s[k][j]);
        hash1[j][val]++;
      }
    }
    for (int j = 0; j < M; j++) {
      if (rev[j])
        ans[j] += countStrings(j, 0, {0, 0});
    }
  }
  for (int i = 0; i < M; i++) {
    printf("%d\n", ans[i]);
  }
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> T;

const int mod1 = 1000000007;
const int base1 = 1009;

const int mod2 = 1000000007;
const int base2 = 1007;

int N, M;
char s[100000][201];
char d[100000][201];
int ans[100000];
bool rev[100000];
map<pair<int, int>, int> hash1[200];
set<pair<int, int>> endd[200];

T connect(T &hash, char c) {
  return (make_pair(1LL * (hash.first + c) * base1 % mod1,
                    1LL * (hash.second + c) * base2 % mod2));
}

int countStrings(int p, int idx, T val) {
  if (d[p][idx] == '\0') {
    return (endd[idx - 1].find(val) != endd[idx - 1].end());
  } else if (d[p][idx] == '*') {
    return (hash1[idx - 1].find(val) != hash1[idx - 1].end()
                ? hash1[idx - 1][val]
                : 0);
  } else if (d[p][idx] == '?') {
    int ret = 0;
    for (char c = 'a'; c <= 'z'; c++) {
      ret += countStrings(p, idx + 1, connect(val, c));
    }
    return (ret);
  } else {
    return (countStrings(p, idx + 1, connect(val, d[p][idx])));
  }
}

int main() {
  scanf("%d %d", &N, &M);
  for (int i = 0; i < N; i++) {
    scanf(" %s", s[i]);
  }
  for (int i = 0; i < M; i++) {
    scanf(" %s", d[i]);
    if (d[i][0] == '*') {
      reverse(d[i], d[i] + strlen(d[i]));
      rev[i] = true;
    }
  }

  const int BACKET = 3000;
  for (int i = 0; i < N; i += BACKET) {
    for (int j = 0; j < 200; j++) {
      hash1[j].clear();
      endd[j].clear();
    }
    for (int k = i; k < min(N, i + BACKET); k++) {
      int len = strlen(s[k]);
      T val = {0, 0};
      for (int j = 0; j < len; j++) {
        val = connect(val, s[k][j]);
        hash1[j][val]++;
      }
      endd[len - 1].insert(val);
    }
    for (int j = 0; j < M; j++) {
      if (!rev[j])
        ans[j] += countStrings(j, 0, {0, 0});
    }
  }

  for (int i = 0; i < N; i++) {
    reverse(s[i], s[i] + strlen(s[i]));
  }

  for (int i = 0; i < N; i += BACKET) {
    for (int j = 0; j < 200; j++) {
      hash1[j].clear();
    }
    for (int k = i; k < min(N, i + BACKET); k++) {
      T val(0, 0);
      int len = strlen(s[k]);
      for (int j = 0; j < len; j++) {
        val = connect(val, s[k][j]);
        hash1[j][val]++;
      }
    }
    for (int j = 0; j < M; j++) {
      if (rev[j])
        ans[j] += countStrings(j, 0, {0, 0});
    }
  }
  for (int i = 0; i < M; i++) {
    printf("%d\n", ans[i]);
  }
}