zoukankan      html  css  js  c++  java
  • ZOJ 3430 Detect the Virus(AC自动机 + 模拟)题解

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

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

    代码:

    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include <iostream>
    #include<algorithm>
    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<int, int> 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<int> 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
    ", ac.match(now, len));
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    结队项目----第一次作业
    小学四则运算(2.0版本)
    小学算法(四则运算)
    (读书笔记)基于CMMI的软件工程及实训指导------第一章软件工程基础
    数学建模------线性规划
    初出茅庐-----微信好友分析与微信机器人
    初出茅庐----数据库的学习应用
    初出茅庐---程序测试与爬虫
    初出茅庐----体育竞技分析
    Unity使用小剧场—创建的按钮On Click()只有MonoScript怎么办
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11176943.html
Copyright © 2011-2022 走看看