zoukankan      html  css  js  c++  java
  • poj 4052(ac自动机)

    题意:自己百度吧!!

    分析:就是通过它的fail指针来找出它的子串就行了,这题其实不难的。这好像还是金华邀请赛的题哦!

    代码实现:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<queue>
    using namespace std;
    struct node{
        int next[26];
        int fail;
        int num;
        void init()
        {
            memset(next,0,sizeof(next));
            fail=0;
            num=0;
        }
    }a[3000010];
    char keyword[2600][1200];
    char S[5200001],temp[5200001];
    int visited[3505];
    int tot,n;
    int ok[3000010];
    
    void chushihua()//初始化
    {
        tot=0;
        a[0].init();
        memset(visited,0,sizeof(visited));
    }
    
    void insert(char *str,int biaohao)//建立字典树
    {
        int index,p=0;
        for(;*str!='';str++)
        {
            index=*str-'A';
            if(a[p].next[index]==0)
            {
                a[++tot].init();
                a[p].next[index]=tot;
            }
            p=a[p].next[index];
        }
        a[p].num=biaohao;
    }
    
    void build_fail()//建立trie图
    {
        queue<int>Q;
        int p,cur,son,i;
        Q.push(0);
        while(!Q.empty())
        {
            p=Q.front();
            Q.pop();
            for(i=0;i<26;i++)
            {    
                if(a[p].next[i]!=0)
                {
                    son=a[p].next[i];
                    cur=a[p].fail;
                    if(p==0)
                        a[son].fail=0;
                    else
                    {
                        while(cur&&a[cur].next[i]==0)
                            cur=a[cur].fail;
                        a[son].fail=a[cur].next[i];
                    }
                    Q.push(son);
                }
                else
                    a[p].next[i]=a[a[p].fail].next[i];
            }
        }
    }
    
    void change(char str[])
    {
        int i,len=0,k=0;
        for(i=0;str[i]!='';i++)
        {
            if(str[i]>='A'&&str[i]<='Z')
                temp[len++]=str[i];
            else 
            {
                i++;
                k=0;//开始的时候这里没加,一直wa,细节啊
                k=k+str[i]-'0';
                i++;
                while(str[i]>='0'&&str[i]<='9')
                {
                    k=k*10+str[i]-'0';
                    i++;
                }
                while(k--)
                    temp[len++]=str[i];
                i++;
                
            }
        }
        temp[len]='';
        strcpy(str,temp);
    }
    
    void solve1()//在主串里出现过的全部标记了
    {
        int i,index,p=0,j;
        for(i=0;S[i]!='';i++)
        {
            index=S[i]-'A';
            p=a[p].next[index];
            if(a[p].num)
            {
                visited[a[p].num]=1;
                continue;//它的子串肯定就不用标记了
            }
            for(j=p;j!=0&&ok[j]==0;j=a[j].fail)
            {
                ok[j]=1;
                visited[a[j].num]=1;
            }
        }
    }
    
    void solve2(char S[],int biaohao)//去掉子串
    {
        int i,index,p=0,j;
        for(i=0;S[i]!='';i++)
        {
            index=S[i]-'A';
            p=a[p].next[index];
            for(j=p;j!=0&&ok[j]==0;j=a[j].fail)
            {
                if(a[j].num&&a[j].num!=biaohao)
                {
                    visited[a[j].num]=0;
                    ok[j]=1;
                }
            }
        }
    }
    
    int main()
    {
        int T,i,res;
        scanf("%d",&T);
        while(T--)
        {
            chushihua();
            res=0;
            scanf("%d",&n);
            getchar();
            for(i=1;i<=n;i++)
            {
                scanf("%s",keyword[i]);
                change(keyword[i]);//把畸形的字符串变成正常的
                insert(keyword[i],i);
            }
            build_fail();
            scanf("%s",S);
            change(S);
            memset(ok,0,sizeof(ok));
            solve1();
            memset(ok,0,sizeof(ok));
            for(i=1;i<=n;i++)
                if(visited[i]==1)
                   solve2(keyword[i],i);
            for(i=1;i<=n;i++)
                if(visited[i]==1)
                    res++;
            printf("%d
    ",res);
        }
        return 0;
    }
  • 相关阅读:
    UNIX环境高级编程——守护进程列表
    UNIX环境高级编程——信号说明列表
    UNIX环境高级编程——进程间通信概念
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/jiangjing/p/3237976.html
Copyright © 2011-2022 走看看