light oj 1427 AC自动机+dfs

1427 - Substring Frequency (II)
Time Limit: 5 second(s) Memory Limit: 128 MB

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 nlines 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

Output for Sample Input

2

5

ababacbabc

aba

ba

ac

a

abc

3

lightoj

oj

light

lit

Case 1:

2

3

1

4

1

Case 2:

1

1

0

Notes

  1. Dataset is huge, use faster I/O methods.
  2. If S is a string then |S| denotes the length of S

 

 

建好字典树、构建好fail指针后,在树上走一遍主串,注意,只需要线性的走一遍就好,不需要走fail

然后建图:

每个点的fail指向的点向这个点建一条边,如果某个点被访问过,那么它的fail以及fail的fail。。。都访问过,所以这样建好图后直接dfs一遍,在回溯的时候把子树节点的访问次数加上来即可

另外,还要用一个hash[]标记每个单词在字典树中的位置的编号

dfs后,直接输出答案就好了

View Code
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int MM = 500005,NC = 26;
vector<int> edge[MM];
int N;
char str[600];
int ans[600];
char s[1000010];
int hash[600];
struct trie{
    int ch[NC],fail,f;
    void init(){
        memset(ch,0,sizeof(ch));
        fail=f=0;
    }
}a[MM];
int cnt,rt,q[MM],front,last;
void Init(){
    cnt=1;
    rt=cnt++;
    a[0].init();
    for(int i=0;i<NC;i++)   a[0].ch[i]=rt;
    a[1].init();
}
void Ins(char *in,int k){
    int now=rt;
    for(;*in;++in){
        int id=*in-'a';
        if(!a[now].ch[id]){
            a[cnt].init();
            a[now].ch[id]=cnt++;
        }
        now=a[now].ch[id];
    }
    hash[k]=now;
}
void build(){
    front=last=0;
    q[front++]=rt;
    while(last<front){
        int t=q[last++];
        for(int i=0;i<NC;i++){
          int tt=a[t].ch[i];
          int ff=a[t].fail;
          if(a[t].ch[i]){
              a[tt].fail=a[ff].ch[i];
              q[front++]=tt;
          }
          else  a[t].ch[i]=a[ff].ch[i];
        }
    }
}
void AC(char *str){
    int i=0,cur=rt;
    for(;str[i];i++){
        int id=str[i]-'a';
        cur=a[cur].ch[id];
        a[cur].f++;
    }
}
void dfs(int u){
     ans[u]=a[u].f;
     for(int i=0;i<edge[u].size();i++) {
           int v=edge[u][i];
           dfs(v);
           ans[u]+=ans[v];
     } 
}
int main(){
    int t,n,ca=1,i;
    scanf("%d",&t);
    while(t--){
        Init();
        scanf("%d",&n);
        scanf("%s",s);
        for(int i=0;i<n;i++){
            scanf("%s",str);
            Ins(str,i);
        }
        build();
        for(i=0;i<MM;i++) edge[i].clear();
        for(i=1;i<cnt;i++)
            edge[a[i].fail].push_back(i);
        memset(ans,0,sizeof(ans));
        AC(s);
        dfs(1);
        printf("Case %d:\n",ca++);
        for(i=0;i<n;i++)
            printf("%d\n",ans[hash[i]]);
    }
    return 0;
}

 

 

posted @ 2012-05-20 13:48  Because Of You  Views(910)  Comments(0Edit  收藏  举报