zoukankan      html  css  js  c++  java
  • 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;
    }
    


  • 相关阅读:
    css3——box-sizing属性
    HTML5存储--离线存储
    微信公众号爆出前端安全漏洞
    Js获取宽高度的归纳集锦总结
    Yii 2 修改 URL 模式为 PATH 模式,并隐藏index.php
    SQL 查询优化 索引优化
    linux提示语言包
    安装linux工作环境
    linux常用命令
    PHP解决抢购、秒杀、抢楼、抽奖等阻塞式高并发库存防控超量的思路方法
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777428.html
Copyright © 2011-2022 走看看