思路:
直接建前后缀tire,然后暴力判断
时间复杂度:因为总和不超过2e6,对于每次询问,不可能都找到2e6个串,这种情况直接map记忆化就行了。
c o d e code code
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
using namespace std;
const int MAXN = 1e6 + 10;
int n, m, tot1, tot2;
int tr1[MAXN * 2][4], tr2[MAXN * 2][4];
vector<int> v1[MAXN * 4], v2[MAXN * 4];
map<pair<int, int>, int> ma;
void add1(string s, int x) {
int p = 0, len = s.size();
for(int i = 0; i < len; i ++) {
char c = s[i];
int c1 = 0;
if(c == 'G') c1 = 1;
if(c == 'U') c1 = 2;
if(c == 'C') c1 = 3;
if(!tr1[p][c1]) ++ tot1, tr1[p][c1] = tot1;
p = tr1[p][c1];
v1[p].push_back(x);
}
}
void add2(string s, int x) {
int p = 0, len = s.size();
for(int i = len - 1; i >= 0; i --) {
char c = s[i];
int c1 = 0;
if(c == 'G') c1 = 1;
if(c == 'U') c1 = 2;
if(c == 'C') c1 = 3;
if(!tr2[p][c1]) ++ tot2, tr2[p][c1] = tot2;
p = tr2[p][c1];
v2[p].push_back(x);
}
}
int query1(string s) {
int p = 0, len = s.size();
for(int i = 0; i < len; i ++) {
char c = s[i];
int c1 = 0;
if(c == 'G') c1 = 1;
if(c == 'U') c1 = 2;
if(c == 'C') c1 = 3;
if(!tr1[p][c1]) return -1;
p = tr1[p][c1];
}
return p;
}
int query2(string s) {
int p = 0, len = s.size();
for(int i = len - 1; i >= 0; i --) {
char c = s[i];
int c1 = 0;
if(c == 'G') c1 = 1;
if(c == 'U') c1 = 2;
if(c == 'C') c1 = 3;
if(!tr2[p][c1]) return -1;
p = tr2[p][c1];
}
return p;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) {
string s;
cin>>s;
add1(s, i);
add2(s, i);
}
while(m --) {
string s1, s2;
cin>>s1>>s2;
int k1 = query1(s1);
int k2 = query2(s2);
if(k1 == -1 || k2 == -1) {
printf("0\n");
continue;
}
if(ma[make_pair(k1, k2)] != 0) {
printf("%d\n", ma[make_pair(k1, k2)]);
continue;
}
int ans = 0;
int i = 0, j = 0, len1 = v1[k1].size(), len2 = v2[k2].size();
while(i < len1 && j < len2) {
if(v1[k1][i] == v2[k2][j]) ans ++, i ++, j ++;
else if(v1[k1][i] < v2[k2][j]) i ++;
else j ++;
}
printf("%d\n", ans);
ma[make_pair(k1, k2)] = ans;
}
return 0;
}