题目链接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=16400
把输入的字符根据下表,转化成value数字,在转化成6位的二进制,载8个二进制一组划分,转化成0~255的数字(ASCII字符的十进制),然后就是AC自动机模版的事了。一个=表示转化得到的二进制末尾要去掉2个0
Value | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Encoding | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | a | b | c | d | e | f |
Value | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
Encoding | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | + | / |
3 二进制 0~255 YmFzZTY0 01100010 01100001 01110011 01100101 00110110 00110100 98 97 115 101 54 52 dmlydXM= 01110110 01101001 01110010 01110101 01110011 118 105 114 117 115 dDog 01110100 00111010 00100000 116 58 32 1 dGVzdDogdmlydXMu 01110100 01100101 01110011 01110100 00111010 00100000 01110110 01101001 01110010 01110101 01110011 00101110 116 101 115 116 58 32 118 105 114 117 115 46 1 QA== 01000000 64 2 QA== 01000000 64 ICAgICAgICA= 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 32 32 32 32 32 32 32 32
尝试五种错误以后终于A了,转化部分写得有些糟
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50010;
struct Trie
{
int next[N][260],fail[N],end[N],id[N];
int root,L;
int newnode()
{
for(int i = 0; i < 257; i++)
next[L][i] = -1;
id[L] = 0;
end[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(int har[], int len)
{
int now = root;
for(int i = 1; i < len; i++)
{
if(next[now][har[i]] == -1)
next[now][har[i]] = newnode();
now = next[now][har[i]];
}
end[now]++;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0; i < 257; i++)
{
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while(!Q.empty())
{
int now = Q.front();
Q.pop();
for(int i = 0; i < 257; i++)
{
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
int query(int har[],int len,int ID)
{
int now = root;
int ans = 0;
for(int i = 1; i < len; i++)
{
now = next[now][har[i]];
int temp = now;
while(temp != root)
{
if(id[temp] != ID)
{
ans += end[temp];
id[temp] = ID;
}
temp = fail[temp];
}
}
return ans;
}
};
char buf[3000];
int hub[18000];
int har[3000];
Trie ac;
int change()
{
int cnt = 0;
int len = strlen(buf);
int tmp;
int k = 0;
for(int i = 0; i < len; i++)
{
if(buf[i] >= 'A' && buf[i] <= 'Z')
{
tmp = buf[i] - 65;
}
else
{
if(buf[i] >= 'a' && buf[i] <= 'z')
{
tmp = buf[i] - 71;
}
else
{
if(buf[i] >= '0' && buf[i] <= '9')
tmp = buf[i]+4;
else
{
if(buf[i] == '+')
{
tmp = 62;
}
else
{
if(buf[i] == '/')
tmp = 63;
}
}
}
}
if(buf[i] == '=')
break;
int j = 6;
while(j--)
{
hub[k+j] = tmp%2;
tmp/=2;//转化成二进制
}
k += 6;
}
k = (k/8)*8;//base64只会添加2个或4个0
tmp = 0;
for(int i = 0; i <= k; i++)
{
if(i%8 == 0)
{
har[cnt++] = tmp;//插入从har[1]开始
tmp = hub[i];
}
else
{
tmp *= 2;
tmp += hub[i];
}
}
return cnt;
}
int main(int argc, char const *argv[])
{
int n,m;
int len;
while(~scanf("%d",&n))
{
ac.init();
for(int i = 1; i <= n; i++)
{
scanf("%s",buf);
len = change();
ac.insert(har,len);
}
ac.build();
scanf("%d",&m);
for(int i = 1; i <= m; i++)
{
scanf("%s",buf);
len = change();
printf("%d\n",ac.query(har,len,i));
}
printf("\n");
}
return 0;
}