HDU-3695 Computer Virus on Planet Pandora(ac自动机模板题)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Cymbals/article/details/82707610

Aliens on planet Pandora also write computer programs like us. Their programs only consist of capital letters (‘A’ to ‘Z’) which they learned from the Earth. On
planet Pandora, hackers make computer virus, so they also have anti-virus software. Of course they learned virus scanning algorithm from the Earth. Every virus has a pattern string which consists of only capital letters. If a virus’s pattern string is a substring of a program, or the pattern string is a substring of the reverse of that program, they can say the program is infected by that virus. Give you a program and a list of virus pattern strings, please write a program to figure out how many viruses the program is infected by.

多模式串匹配,只不过反着也算。

正着跑一遍倒着跑一遍就好了。

输入比较奇葩,要进行展开,把那个数字看成小于10了一直wa…..

单独给个scanf就ac了。

还有就是重复使用char数组记得最后加‘\0’终止符。

其实这里还是string好用。

记录模板。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1005 * 251;
char pa[5100005];

struct AC_Automaton {
    int next[maxn][26];
    int fail[maxn];
    int end[maxn];
    int sz, root;

    int newNode() {
        for(int i = 0; i < 26; i++) {
            next[sz][i] = -1;
        }
        fail[sz] = -1;
        end[sz] = 0;
        return sz++;
    }

    void init() {
        sz = 0;
        root = newNode();
    }

    void add(char s[]) {
        int p = root, c;
        for(int i = 0, len = strlen(s); i < len; i++) {
            c = s[i] - 'A';
            if(next[p][c] == -1) {
                next[p][c] = newNode();
            }
            p = next[p][c];
        }
        end[p] = 1;
    }


    void getFail() {
        queue<int> q;
        for(int i = 0; i < 26; i++) {
            if(~next[root][i]) {
                fail[next[root][i]] = root;
                q.push(next[root][i]);
            } else {
                next[root][i] = root;
            }
        }
        while(!q.empty()) {
            int p = q.front();
            q.pop();
            for(int i = 0; i < 26; i++) {
                if(~next[p][i]) {
                    fail[next[p][i]] = next[fail[p]][i];
                    q.push(next[p][i]);
                } else {
                    next[p][i] = next[fail[p]][i];
                }
            }
        }
    }

    int solve() {
        int p = root, ans = 0, len = strlen(pa);
        for(int i = 0; i < len; i++) {
            p = next[p][pa[i] - 'A'];
            for(int t = p; t && ~end[t]; t = fail[t]) {
                ans += end[t];
                end[t] = -1;
            }
        }
        p = root;
        for(int i = len - 1; i >= 0; i--) {
            p = next[p][pa[i] - 'A'];
            for(int t = p; t && ~end[t]; t = fail[t]) {
                ans += end[t];
                end[t] = -1;
            }
        }
        return ans;
    }
} ac;


int main() {
    int t, n;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        ac.init();
        while(n--) {
            scanf("%s", pa);
            ac.add(pa);
        }
        ac.getFail();
        char in = getchar();
        int idx = 0;
        while(in = getchar(), in != '\n') {
            if(in != '[') {
                pa[idx++] = in;
                continue;
            }
            int num;
            scanf("%d", &num);
            in = getchar();
            for(int i = 0; i < num - '0'; i++) {
                pa[idx++] = in;
            }
            getchar();
        }
        pa[idx] = '\0';
        printf("%d\n", ac.solve());
    }
    return 0;
}

吐槽:无论是ac自动机还是后缀自动机,都只有写在结构体里才有感觉自己建了一个“自动机”啊!还有就是写在结构体里就不怕名称跟stl冲突了,找回了写java的感觉。

猜你喜欢

转载自blog.csdn.net/Cymbals/article/details/82707610