LightOJ 1427 Substring Frequency (II)(AC自动机裸)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1427

题意:给定n个模式串,一个文本串,求每个模式串在文本串中出现的次数。

思路:AC自动机裸题。

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>

using namespace std;

#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ceil(x, y) (((x) + (y) - 1) / (y))

const int SIZE = 30;
const int N = 3e5 + 10;
const int M = 5e2 + 10;
const int INF = 0x7f7f7f7f;
const int MAX_WORD = 1e6 + 10;
const double EPS = 1e-9;
const int MOD = 2015;

int sz;
int ch[N][SIZE];
int f[N];
int val[N];
bool ed[N];
char txt[MAX_WORD];
char mod[M][M];

int newnode() {
    memset(ch[sz], 0, sizeof(ch[sz]));
    f[sz] = 0;
    val[sz] = 0;
    ed[sz] = false;
    return sz++;
}

void init() {
    sz = 0;
    newnode();
}

void insert(char *s) {
    int u = 0;
    for (int i = 0; s[i]; i++) {
        int v = s[i] - 'a';
        if (!ch[u][v])
            ch[u][v] = newnode();
        u = ch[u][v];
    }
    ed[u] = true;
}

void getfail() {
    queue<int> q;

    for (int i = 0; i < SIZE; i++)
        if (ch[0][i])
            q.push(ch[0][i]);

    while (!q.empty()) {
        int r = q.front();
        q.pop();
        for (int i = 0; i < SIZE; i++) {
            int v = ch[r][i];
            if (v) {
                q.push(v);
                int u = f[r];
                while (u && !ch[u][i]) u = f[u];
                f[v] = ch[u][i];
            }
            else ch[r][i] = ch[f[r]][i];
        }
    }
}

void find(char *s) {
    getfail();
    int u = 0;
    for (int i = 0; s[i]; i++) {
        int v = s[i] - 'a';
        u = ch[u][v];
        int t = u;
        while (t) {
            if (ed[t])
                val[t]++;
            t = f[t];
        }
    }
}

int main() {
    int t_case;
    scanf("%d", &t_case);
    for (int i_case = 1; i_case <= t_case; i_case++) {
        int n;
        scanf("%d%s", &n, txt);
        init();
        for (int i = 0; i < n; i++) {
            scanf("%s", mod[i]);
            insert(mod[i]);
        }
        find(txt);
        printf("Case %d:\n", i_case);
        for (int i = 0; i < n; i++) {
            int u = 0;
            for (int j = 0; mod[i][j]; j++) 
                u = ch[u][mod[i][j] - 'a'];
            printf("%d\n", val[u]);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值