```cpp
#include <iostream>
#include <unordered_map>
#include <string>
#include <queue>
#include <vector>
using namespace std;
using String = basic_string<int>; // 可通过 substr 取子序列
const int kMaxN = 5e6 + 5, kCharSet = 26 * 26;
struct Node {
unordered_map<int, int> ch;
int fail, sum;
};
vector<Node> tr;
int n, q;
string s, t;
void insert(const String &s) {
int p = 0;
for (int i : s) {
if (!tr[p].ch[i]) {
tr.emplace_back();
tr[p].ch[i] = tr.size() - 1;
}
p = tr[p].ch[i];
}
tr[p].sum++;
}
void build() {
queue<int> q;
// 初始化根节点的所有子节点
for (auto &i : tr[0].ch) {
tr[i.second].fail = 0;
q.push(i.second);
}
// BFS 顺序即按层次的拓扑序
vector<int> order;
for (; q.size(); q.pop()) {
int p = q.front();
order.push_back(p);
for (auto &i : tr[p].ch) {
int pty = i.first;
int mmt = i.second;
int f = tr[p].fail;
while (f && !tr[f].ch.count(pty)) {
f = tr[f].fail;
}
if (tr[f].ch.count(pty)) {
tr[mmt].fail = tr[f].ch[pty];
} else {
tr[mmt].fail = 0;
}
q.push(mmt);
}
}
// 按拓扑序把 fail 链上的出现次数累加下来
for (int u : order) {
tr[u].sum += tr[tr[u].fail].sum;
}
}
long long match(const String &s) {
if (s.empty()) {
return 0;
}
int p = 0;
long long res = 0;
for (int c : s) {
while (p && !tr[p].ch.count(c)) {
p = tr[p].fail;
}
auto it = tr[p].ch.find(c);
if (it != tr[p].ch.end()) {
p = it->second;
}
res += tr[p].sum;
}
return res;
}
int calc(char a, char b) {
return (a - 'a') * 26 + (b - 'a');
}
String convert(const string &a, const string &b) {
String res(a.size(), 0);
for (int i = 0; i < (int)a.size(); i++) {
res[i] = calc(a[i], b[i]);
}
return res;
}
String interval(const String &s, int l, int r) {
if (l > r) {
return String();
}
return s.substr(l, r - l + 1);
}
int main() {
cin.tie(0)->sync_with_stdio(0);
tr.reserve(5e6);
tr.emplace_back();
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> s >> t;
String lrh = convert(s, t);
insert(lrh);
}
build();
while (q--) {
cin >> s >> t;
if (s.size() != t.size()) {
cout << "0\n";
continue;
}
String lrh = convert(s, t);
int n = s.size(), wyy = 0, zrr = n - 1;
// [0, wyy) 是最长公共前缀,(zrr, n - 1] 是最长公共后缀
// [wyy, zrr] 是模式串必须覆盖的区域
for (; wyy < n && s[wyy] == t[wyy]; wyy++) { }
for (; zrr >= 0 && s[zrr] == t[zrr]; zrr--) { }
if (wyy > zrr) { // 模式串无须覆盖任何区域,直接输出所有匹配数
cout << match(lrh) << '\n';
} else { // 用容斥求出至少覆盖了 [wyy, zrr] 的匹配数量
cout << match(lrh) - match(interval(lrh, 0, zrr - 1)) - match(interval(lrh, wyy + 1, n - 1)) + match(interval(lrh, wyy + 1, zrr - 1)) << '\n';
}
}
return 0;
}
```