zoukankan      html  css  js  c++  java
  • ZOJ 3228(AC自动机+修改的匹配)

    题目大意:给出一个字符串和若干个单词,问这些单词在字符串里面出现了多少次。单词前面为0表示这个单词可重叠出现,1为不可重叠出现。

    分析:可重叠出现的单词可以直接用ac自动机就解决。至于不可重叠的单词,可以用一个数组来记录下每个这种单词上一次出现的位置,假如当前得到这个单词的位置和上一次的位置之间足够放下一个单词(即两个位置的坐标差大于等于单词长度)时才算一次,具体的可以看程序。

    //#pragma comment(linker, "/STACK:102400000")
    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<stack>
    #include<vector>
    #define tree int o,int l,int r
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define lo o<<1
    #define ro o<<1|1
    #define pb push_back
    #define mp make_pair
    #define ULL unsigned long long
    #define LL long long
    #define inf 0x7fffffff
    #define eps 1e-7
    #define N 610009
    #define M 26
    using namespace std;
    int m,n,T,t,x,y,u;
    int ch[N][M],v[2][N],sz;
    int f[N],last[N];
    char str[100009][10],s[100009],len[100009];
    int pre[2][100009],flag[100009],num[100009];
    int pos[100009];
    void init()
    {
        sz=1;
        for(int i=0; i<100009; i++)pre[0][i]=pre[1][i]=-1;
        memset(pos,-1,sizeof(pos));
        memset(num,0,sizeof(num));
        memset(ch[0],0,sizeof(ch[0]));
        memset(v,0,sizeof(v));
        memset(last,0,sizeof(last));
    }
    int idx(char c)
    {
        return c-'a';
    }
    void insert(char str[],int val,int sub)
    {
        int u=0;
        for(int i=0; str[i]; i++)
        {
            int c=idx(str[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        if(v[sub][u]!=0)
            pre[sub][val]=v[sub][u];
        v[sub][u]=val;
    }
    void getac()
    {
        f[0]=0;
        queue<int>q;
        for(int c=0; c<M; c++)
        {
            int u=ch[0][c];
            if(u)
            {
                f[u]=0;
                q.push(u);
                last[u]=0;
            }
        }
        while(!q.empty())
        {
            int r=q.front();
            q.pop();
            for(int c=0; c<M; c++)
            {
                int u=ch[r][c];
                if(!u)
                {
                    ch[r][c]=ch[f[r]][c];
                }
                else
                {
                    q.push(u);
                    int s=f[r];
                    f[u]=ch[s][c];
                    last[u]=(v[0][f[u]]||v[1][f[u]])?f[u]:last[f[u]];
                }
            }
        }
    }
    void print(int u,int i)
    {
        if(u)
        {
            if(v[0][u])
            num[v[0][u]]++;
            if(v[1][u]&&i-pos[v[1][u]]>=len[v[1][u]])//特殊处理
            {
                num[v[1][u]]++;
                pos[v[1][u]]=i;//别忘!
            }
            print(last[u],i);
        }
    }
    void find(char str[])
    {
        int n=strlen(str);
        int j=0;
        for(int i=0;i<n;i++)
        {
            int c=idx(str[i]);
            j=ch[j][c];
            if(v[0][j]||v[1][j])print(j,i);
            else if(last[j])print(last[j],i);
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
        int ncase=0;
        scanf("%d",&T);
        while(scanf("%s",s)==1)
        {
            init();
            scanf("%d",&n);
            for(int i=1; i<=n; ++i)
            {
                scanf("%d%s",&flag[i],str[i]);
                len[i]=strlen(str[i]);
                insert(str[i],i,flag[i]);
            }
            getac();
            find(s);
    
            for(int i=n;i>=1;i--)
            if(pre[flag[i]][i]!=-1)
            {
                num[pre[flag[i]][i]]=num[i];
            }
            printf("Case %d
    ",++ncase);
            for(int i=1;i<=n;i++)
            printf("%d
    ",num[i]);
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Python单元测试unittest加载方式之二:加载测试套件
    Python单元测试unittest加载方式之二:加载测试套件
    Python单元测试unittest加载方式之一:unittestmain()启动单元测试模块
    和优秀的人相处
    耐心和恒心
    ubuntu下FTP文件目录共享
    一个不错的编译调试方法
    qt 程序异常崩溃
    minigui SetTimer(hwnd, id, speed)
    minigui 按钮点击弹窗外部 弹窗消失功能 WS_EX_TRANSPARENT
  • 原文地址:https://www.cnblogs.com/sbaof/p/3376456.html
Copyright © 2011-2022 走看看