zoj 3430(ac自动机)

来源:互联网 发布:淮南网络宾馆 编辑:程序博客网 时间:2024/06/06 02:56

题意:给出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;}
0 0
原创粉丝点击