HDU 3065 病毒侵袭持续中

询问每个模式串在文本传中出现的次数。

文本串中出现的字符不一定都是大写字母,只需要在匹配的时候,对文本串进行特殊处理,将连续的大写字母段当成合法的一个文本串即可。

然后……就是简单的统计了。





 

#include <cstdio>

#include <algorithm>

#include <vector>

#include <queue>

#include <cstring>

#include <string>

using namespace std;

int n, cnt[1010];

char s[1010][55], t[2000010], a[2000010];



struct AC_Automata {

    #define N 60003

    #define M 26

    int ch[N][M], f[N], val[N], last[N], sz;



    void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }

    int idx(char c) { return c-'A'; }



    void insert(char s[], int v) {

        int u = 0;

        for (int i=0; s[i]; i++) {

            int c = idx(s[i]);

            if (!ch[u][c]) {

                memset(ch[sz], 0, sizeof(ch[sz]));

                val[sz] = 0;

                ch[u][c] = sz++;

            }

            u = ch[u][c];

        }

        val[u] = v;

    }

    void build() {

        queue<int> q;

        f[0] = 0;

        for (int c=0; c<M; c++) {

            int u = ch[0][c];

            if (u) { f[u] = last[u] = 0; q.push(u); }

        }

        while (!q.empty()) {

            int r = q.front(); q.pop();

            for (int c=0; c<M; c++) {

                int u = ch[r][c];

                if (!u) { ch[r][c] = ch[f[r]][c]; continue; }

                q.push(u);

                f[u] = ch[f[r]][c];

                last[u] = val[f[u]] ? f[u] : last[f[u]];

            }

        }

    }

    void find(char s[]) {

        int j = 0;

        for (int i=0; s[i]; i++) {

            int c = idx(s[i]);

            j = ch[j][c];

            if (val[j]) print(j);

            else if (last[j]) print(last[j]);

        }

    }

    void print(int j) {

        if (j) {

            cnt[val[j]]++;

            print(last[j]);

        }

    }

} ac;





int main() {

#ifndef ONLINE_JUDGE

    freopen("in.txt", "r", stdin);

#endif

    while (scanf(" %d", &n) == 1) {

        ac.clear();

        memset(cnt, 0, sizeof(cnt));



        getchar();

        for (int i=1; i<=n; i++) {

            gets(s[i]); ac.insert(s[i], i);

        }

        ac.build();



        gets(t);

        int j = 0;

        bool flag = false;

        for (int i=0; t[i]; i++) {

            if (t[i] <= 'Z' && t[i] >= 'A') { flag = true; a[j++] = t[i]; }

            else if (flag) {

                a[j] = 0; j = 0;

                flag = false;

                ac.find(a);

            }

        }

        if (flag) {

            a[j] = 0; j = 0;

            flag = false; ac.find(a);

        }



        for (int i=1; i<=n; i++)

            if (cnt[i]) printf("%s: %d\n", s[i], cnt[i]);

    }

    return 0;

}


 

 

你可能感兴趣的:(HDU)