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

J - Substring Frequency (II)
Time Limit: 5000 MS      Memory Limit: 131072 KB      64bit IO Format: %lld & %llu

Description

A string is a finite sequence of symbols that are chosen from an alphabet. In this problem you are given a string T and n queries each with a stringPi, where the strings contain lower case English alphabets only. You have to find the number of times Pi occurs as a substring of T.

Input

Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with a line containing an integer n (1 ≤ n ≤ 500). The next line contains the string T (1 ≤ |T| ≤ 106). Each of the next n lines contains a string Pi (1 ≤ |Pi| ≤ 500).

Output

For each case, print the case number in a single line first. Then for each string Pi, report the number of times it occurs as a substring of T in a single line.

Sample Input

2

5

ababacbabc

aba

ba

ac

a

abc

3

lightoj

oj

light

lit

Sample Output

Case 1:

2

3

1

4

1

Case 2:

1

1

0


题意:裸的AC自动机,问一篇文章中给出的匹配串各出现多少次。

一直wa一直wa,拿壕的代码测试每个代码块却都可以AC,单个测部分测都可以AC......于是开始怀疑人生= =...

崩溃边缘发现是答案数组开小了,导致一直wa。

一个数组就搞得整个代码都过不了,嗯...莫名好难过..........


#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <iostream>
#include <assert.h>
#define INF 0x3f3f3f3f
using namespace std;
const int M = 1e6 + 10;
const int SIZE = 30;
const int N = 3e5 + 10;
const int MAXN = 510;

char str[MAXN][MAXN];
int tricnt;
int ch[N][SIZE];
int fails[N];
int ed[N];
//bool vis[N];
char txt[M];
int ans[N]; //就是这个数组!!!!!!wa了我一下午...........


int newnode()
{
  memset(ch[tricnt], 0, sizeof(ch[tricnt]));
  fails[tricnt] = 0;
  ed[tricnt] = 0;
  //vis[tricnt] = false;
  return tricnt++;
}

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

int trinsert(char* s)
{
  int u = 0;
  int len = strlen(s);
  int v;
  for (int i = 0; i < len; i++) {
    v = s[i] - 'a';
    if (!ch[u][v])
      ch[u][v] = newnode();
    u = ch[u][v];
  }
  ed[u] = 1;
  //cout << u << "~" << ed[u] << endl;
  return u;
}


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 = fails[r];
        while (u && !ch[u][i])
          u = fails[u];
        fails[v] = ch[u][i];
      }
      else ch[r][i] = ch[fails[r]][i];
    }
  }
}

int query(char* s)
{
  getfail();
  int u = 0;
  int p, v;
  for (int i = 0; s[i]; i++) {
    v = s[i] - 'a';
    //while (u && !ch[u][v]) u = fails[u];
    u = ch[u][v];
    p = u;
    while (p) {
      if (ed[p]) {
        ans[p]++;
        //vis[p] = true;
      }
      p = fails[p];
    }
  }
}


int main()
{
  int T;
  cin >> T;
  for (int casecnt = 1; casecnt <= T; casecnt++) {
    int n;
    scanf("%d", &n);
    init();
    memset(ans, 0, sizeof(ans));
    scanf("%s", txt);
    for (int i = 0; i < n; i++) {
      scanf("%s", str[i]);
      trinsert(str[i]);
    }
    query(txt);
    printf("Case %d:\n", casecnt);
    for (int i = 0; i < n; i++) {
      printf("%d\n", ans[trinsert(str[i])]);
    }
  }
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值