题意:给出n个模式串,是以base64编码的,m个目标串,也是base64编码,问每个目标串里有多少种模式串。base64是把普通ASCII字符二进制表示的每6位截断对应一个最大编号到63的字符表可以对应一个字符,也就是每四个字符对应三个个普通字符,不够就末尾补零。补两个0是”=”,补四个0是”==”。
题解:先把所有给出的串都先解码为普通的字符串,然后是自动机模板解法。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
const int N = 33000;
const int SIGMA_SIZE = 256;
const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char str[3000];
char str2[3000];
int Next[N][SIGMA_SIZE], val[N], fail[N], sz, n, m, vis[550];
map<char, unsigned char> mp;
int decode(char *s) {
int cnt = 0, len = strlen(s);
while (s[len - 1] == '=')
len--;
for (int i = 0; i < len; i += 4) {
str[cnt++] = (mp[s[i]] << 2) | (mp[s[i + 1]] >> 4);
if (i + 2 < len)
str[cnt++] = (mp[s[i + 1]] << 4) | (mp[s[i + 2]] >> 2);
if (i + 3 < len)
str[cnt++] = (mp[s[i + 2]] << 6) | mp[s[i + 3]];
}
return cnt;
}
void init() {
sz = 1;
memset(Next[0], 0, sizeof(Next[0]));
val[0] = 0;
}
void insert(unsigned char *s, int len, int v) {
int u = 0;
for (int i = 0; i < len; i++) {
if (!Next[u][s[i]]) {
memset(Next[sz], 0, sizeof(Next[sz]));
val[sz] = 0;
Next[u][s[i]] = sz++;
}
u = Next[u][s[i]];
}
val[u] = v;
}
void getFail() {
queue<int> Q;
fail[0] = 0;
for (int i = 0; i < SIGMA_SIZE; i++) {
if (Next[0][i]) {
fail[Next[0][i]] = 0;
Q.push(Next[0][i]);
}
}
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for (int i = 0; i < SIGMA_SIZE; i++) {
if (!Next[u][i])
Next[u][i] = Next[fail[u]][i];
else {
fail[Next[u][i]] = Next[fail[u]][i];
Q.push(Next[u][i]);
}
}
}
}
int query(unsigned char *s, int len) {
int u = 0, cnt = 0;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < len; i++) {
u = Next[u][s[i]];
int temp = u;
while (temp != 0) {
if (val[temp])
vis[val[temp]] = 1;
temp = fail[temp];
}
}
for (int i = 1; i <= n; i++)
if (vis[i])
cnt++;
return cnt;
}
int main() {
for (int i = 0; i < 64; i++)
mp[cb64[i]] = i;
while (scanf("%d", &n) == 1) {
init();
for (int i = 1; i <= n; i++) {
scanf("%s", str2);
int len = decode(str2);
insert(str, len, i);
}
getFail();
scanf("%d", &m);
while (m--) {
scanf("%s", str2);
int len = decode(str2);
printf("%d\n", query(str, len));
}
printf("\n");
}
return 0;
}