ZOJ3228【AC自动机】

先贡献几个数据(大笑没用别怪我):

/*
ab
4
0 ab
1 ab
0 ab
1 ab
abababac
4
0 aba
1 aba
0 abab
1 abab
abcdefghijklmnopqrstuvwxyz
3
0 abc
1 def
1 jmn
abcdabcd
3
0 cd
0 abcd
0 abcd
*/


思路:

因为要考虑不可重复和可重复,而且输入那一堆串还有重复的,如果可以重复,那么就是正常做法,回溯到根,全部相加;如果不可以重复,那么标记位置上的后缀串的长度。

ps:因为是书上例题,然后照着书上代码搞搞搞,没想到搞崩了。因为书上代码是错的!他开了一个flag表示这个位置是否存在后缀串,但是他找的时候= =、第一个错误;还有他没有把fail指针回溯到根,第二个错误,不过这个flag数组搞的很好?(其实并没有。。。贴第一发自己的,第二发书上已改正的代码)

MY CODE

//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;

const int N=1e6+10;
int g[600010][26],word[N],fail[N],sz;
char txt[N],ss[N];
int ans[N][2],last[N],len[N],pos[100010],n,id[100010];
int flag[N];

int INS()
{
    int p=0;
    int lens=strlen(ss);
    int index;
    for(int i=0;i<lens;i++){
        index=ss[i]-'a';
        if(g[p][index]==0){
            memset(g[sz],0,sizeof(g[sz]));
            last[sz]=-1;
            flag[sz]=0;
            word[sz]=0;
            ans[sz][0]=ans[sz][1]=0;
            g[p][index]=sz++;
        }
        p=g[p][index];
    }
    word[p]=1;
    flag[p]=1;
    len[p]=lens;
    return p;
}

void Build_fail()
{
    int p=0;
    queue<int>que;
    for(int i=0;i<26;i++){
        if(g[p][i])
        {
            que.push(g[p][i]);
            fail[g[p][i]]=0;
        }
    }
    while(!que.empty())
    {
        p=que.front();que.pop();
        for(int i=0;i<26;i++){
            int u=g[p][i];
            if(!u)
                g[p][i]=g[fail[p]][i];
            else{
                que.push(u);
                int v=fail[p];      //取父节点的fail指针去匹配
                while(v && !g[v][i])
                    v=fail[v];
                fail[u]=g[v][i];
            }
        }
    }
}

void solve()
{
    int p=0;
    int index,lens=strlen(txt);
    for(int i=0;i<lens;i++)
    {
        index=txt[i]-'a';
        p=g[p][index];
        int temp=p;
        while(temp){    //回溯到根
            if(word[temp])
            {
                ans[temp][0]++;
                if((i-last[temp])>=len[temp])
                {
                    ans[temp][1]++;
                    last[temp]=i;
                }
            }
            temp=fail[temp];
        }
    }
}

int main()
{
    int cas=1;
    while(~scanf("%s",txt))
    {
        memset(g[0],0,sizeof(g[0]));
        sz=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%s",&id[i],ss);
            pos[i]=INS();
        }
        Build_fail();
        solve();
//        for(int i=1;i<sz;i++)
//            printf("%d %d
",ans[i][0],ans[i][1]);
        printf("Case %d
",cas++);
        for(int i=1;i<=n;i++)
            printf("%d
",ans[pos[i]][id[i]]);
        puts("");
    }
    return 0;
}

BOOK CODE

//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;

const int N=1e6+10;
int g[600010][26],word[N],fail[N],sz;
char txt[N],ss[N];
int ans[N][2],last[N],len[N],pos[100010],n,id[100010];
int flag[N];

int INS()
{
    int p=0;
    int lens=strlen(ss);
    int index;
    for(int i=0;i<lens;i++){
        index=ss[i]-'a';
        if(g[p][index]==0){
            memset(g[sz],0,sizeof(g[sz]));
            last[sz]=-1;
            flag[sz]=0;
            word[sz]=0;
            ans[sz][0]=ans[sz][1]=0;
//            fail[sz]=0;
            g[p][index]=sz++;
        }
        p=g[p][index];
    }
    word[p]=1;
    flag[p]=1;
    len[p]=lens;
    return p;
}

void Build_fail()
{
    int p=0;
    queue<int>que;
    for(int i=0;i<26;i++){
        if(g[p][i])
        {
            que.push(g[p][i]);
            fail[g[p][i]]=0;
        }
    }
    while(!que.empty())
    {
        p=que.front();que.pop();
        for(int i=0;i<26;i++){
            int u=g[p][i];
            if(!u)
                g[p][i]=g[fail[p]][i];
            else{
                que.push(u);
                fail[u]=g[fail[p]][i];
                flag[u]|=flag[fail[u]];
            }
        }
    }
}

void solve()
{
    int p=0;
    int index,lens=strlen(txt);
    for(int i=0;i<lens;i++)
    {
        index=txt[i]-'a';
        p=g[p][index];
        int temp=p;
        while(temp&&!flag[temp])
            temp=fail[temp];
        while(temp){
            if(word[temp])
            {
                ans[temp][0]++;
                if((i-last[temp])>=len[temp])
                {
                    ans[temp][1]++;
                    last[temp]=i;
                }
            }
            temp=fail[temp];
        }
    }
}

int main()
{
    int cas=1;
    while(~scanf("%s",txt))
    {
        memset(g[0],0,sizeof(g[0]));
        sz=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%s",&id[i],ss);
            pos[i]=INS();
        }
        Build_fail();
        solve();
        printf("Case %d
",cas++);
        for(int i=1;i<=n;i++)
            printf("%d
",ans[pos[i]][id[i]]);
        puts("");
    }
    return 0;
}


原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777428.html