ZOJ 3430 Detect the Virus(AC自动机 + 模拟)题解
阅读原文时间:2023年07月08日阅读:1

题意:问你主串有几种模式串。但是所有串都是加密的,先解码。解码过程为:先把串按照他给的映射表变成6位数二进制数,然后首尾衔接变成二进制长串,再8位8位取变成新的数,不够的补0。因为最多可能到255,所以不能用char存,要用int。

思路:模拟乱搞一下,加个板子完事。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 550 * 64 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
char s[maxn];
int bit[maxn * 8], now[maxn * 8];
map change;
void init(){
change.clear();
for(int i = 0; i <= 25; i++) change['A' + i] = i; for(int i = 26; i <= 51; i++) change['a' + i - 26] = i; for(int i = 52; i <= 61; i++) change['0' + i - 52] = i; change['+'] = 62; change['/'] = 63; } int sp(){ int len = strlen(s); int num = 0; for(int i = 0; i < len; i++){ if(s[i] == '='){ num -= 2; continue; } int k = change[s[i]]; for(int j = 5; j >= 0; j--){
bit[num++] = ((k & (1 << j)) == 0? 0 : 1);
}
}
int cnt = 0;
for(int i = 0; i < num; i += 8){
now[cnt] = 0;
for(int j = i; j <= i + 7; j++){
now[cnt] = now[cnt] * 2 + bit[j];
}
cnt++;
}
return cnt;
}

struct Aho{
struct state{
int next[260];
int fail, cnt;
}node[maxn];
int size;
queue q;

void init(){  
    size = 0;  
    newtrie();  
    while(!q.empty()) q.pop();  
}

int newtrie(){  
    memset(node\[size\].next, 0, sizeof(node\[size\].next));  
    node\[size\].cnt = node\[size\].fail = 0;  
    return size++;  
}

void insert(int s\[\], int len, int id){  
    int now = 0;  
    for(int i = 0; i < len; i++){  
        int c = s\[i\];  
        if(node\[now\].next\[c\] == 0){  
            node\[now\].next\[c\] = newtrie();  
        }  
        now = node\[now\].next\[c\];  
    }  
    node\[now\].cnt = id;  
}

void build(){  
    node\[0\].fail = -1;  
    q.push(0);

    while(!q.empty()){  
        int u = q.front();  
        q.pop();  
        for(int i = 0; i < 260; i++){  
            if(node\[u\].next\[i\]){  
                if(u == 0) node\[node\[u\].next\[i\]\].fail = 0;  
                else{  
                    int v = node\[u\].fail;  
                    while(v != -1){  
                        if(node\[v\].next\[i\]){  
                            node\[node\[u\].next\[i\]\].fail = node\[v\].next\[i\];  
                            break;  
                        }  
                        v = node\[v\].fail;  
                    }  
                    if(v == -1) node\[node\[u\].next\[i\]\].fail = 0;  
                }  
                q.push(node\[u\].next\[i\]);  
            }  
        }  
    }  
}

set<int> res;  
void get(int u){ //匹配规则  
    while(u){  
        if(node\[u\].cnt) res.insert(node\[u\].cnt);  
        u = node\[u\].fail;  
    }  
}

int match(int s\[\], int len){  
    res.clear();  
    int ret = 0, now = 0;  
    for(int i = 0; i < len; i++){  
        int c = s\[i\];  
        if(node\[now\].next\[c\]){  
            now = node\[now\].next\[c\];  
        }  
        else{  
            int p = node\[now\].fail;  
            while(p != -1 && node\[p\].next\[c\] == 0){  
                p = node\[p\].fail;  
            }  
            if(p == -1) now = 0;  
            else now = node\[p\].next\[c\];  
        }  
        get(now);  
    }  
    return res.size();  
}  

}ac;
int main(){
init();
int n;
while(~scanf("%d", &n)){
ac.init();
for(int i = 1; i <= n; i++){
scanf("%s", s);
int len = sp();
ac.insert(now, len, i);
}
ac.build();
int m;
scanf("%d", &m);
while(m--){
scanf("%s", s);
int len = sp();
printf("%d\n", ac.match(now, len));
}
printf("\n");
}
return 0;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章