zoukankan      html  css  js  c++  java
  • [TJOI2013]单词

    [TJOI2013]单词

    题目描述

    小张最近在忙毕设,所以一直在读论文。一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次。

    输入输出格式

    输入格式:

    第一行一个整数N,表示有N个单词。接下来N行每行一个单词,每个单词都由小写字母(a-z)组成。(N≤200)

    输出格式:

    输出N个整数,第i行的数表示第i个单词在文章中出现了多少次。

    本来是最近想用刚学的AC自动机上的,结果出锅了,WA了几次,发现不对劲

    先放一下自己的傻吊代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+7;
    int m,n,k,cnt;
    struct Tree
    {
        int ch[27];
        int fail;
        int end;
    } AC[N];
    string s[N];
    struct question
    {
        int pos;
        int num;
    } ans[N];
    void build(string s,int numm)
    {
        int l=s.length(),u=0;
        for (int i=0;i<l;i++)
        {
            int c=s[i]-'a';
            if (AC[u].ch[c]==0)  AC[u].ch[c]=++cnt;
            u=AC[u].ch[c]; 
        }
        AC[u].end=numm;
    }
    void get_fail()
    {
        queue<int> que;
        int u=0;
        for (int i=0;i<26;i++)
        if (AC[u].ch[i])
        {
            AC[AC[u].ch[i]].fail=0;
            que.push(AC[u].ch[i]);
        }
        while (!que.empty())
        {
            int x=que.front();que.pop();
            for (int i=0;i<26;i++)
            if (AC[x].ch[i])
            {
                AC[AC[x].ch[i]].fail=AC[AC[x].fail].ch[i];
                que.push(AC[x].ch[i]);
            }
            else AC[x].ch[i]=AC[AC[x].fail].ch[i];
        }
    }
    void AC_query(string s)
    {
        int l=s.length(),u=0;
        for (int i=0;i<l;i++)
        {
            int c=s[i]-'a';
            u=AC[u].ch[c];
            for (int t=u;t;t=AC[t].fail)
            ans[AC[t].end].num++;
        }
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            cin>>s[i];
            int l=s[i].length();
            s[l]='{';
            s[0]+=s[i];
            build(s[i],i);
            ans[i].pos=i;
            ans[i].num=0;
        }
        AC[0].fail=0;
        get_fail();
        AC_query(s[0]);
        for (int i=1;i<=n;i++)    printf("%d
    ",ans[i].num);
        return 0;
    }

    后来呢看了眼数据范围,疑,200,直接kmp上吧 

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e7+7;
    int kmp[N],ans[N];
    int m,n;
    string s[N];
    void solve(int k)
    {
        memset(kmp,0,sizeof(kmp));
        int j=0,p=0;
        int l1=s[0].length();
        int l2=s[k].length();
        for (int i=2;i<=l2;i++)
        {
            while (j&&s[k][j+1]!=s[k][i]) j=kmp[j];
            if (s[k][j+1]==s[k][i]) j++;
            kmp[i]=j;
        }
        j=0;
        for (int i=1;i<=l1;i++)
        {
            while (j&&s[k][j+1]!=s[0][i]) j=kmp[j];
            if (s[k][j+1]==s[0][i]) j++;
            if (j==l2)
            {
                p++;
                j=kmp[j];
            }
        }
        ans[k]=p;
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            cin>>s[i];
            string ss=s[i];
            ss='#'+ss;
            s[0]+=ss;
            int l=s[i].length();
            for (int j=l;j>=1;j--) s[i][j]=s[i][j-1];
        }
        int l=s[0].length();
        for (int i=l;i>=1;i--) s[0][i]=s[0][i-1];
        for (int i=1;i<=n;i++)
        solve(i);
        for (int i=1;i<=n;i++)
        printf("%d
    ",ans[i]);
        return 0;
    }

    最后一个点超时,不过吸一下O2就好了

    其实还是用cin读入的事,不过不想改了啊,啦啦啦

    慢即是快,细则是能,于小处铸迤逦
  • 相关阅读:
    iOS中GestureRecognizer的6大手势与代理方法详细使用
    使用pan手势实现抽屉效果
    mfc HackerTools释放资源
    mfc HackerTools防止程序双开
    FLV简介
    AAC简介
    H.264简介
    PCM简介
    YUV格式
    编译ffmpeg(第一次),实现JPG转MP4
  • 原文地址:https://www.cnblogs.com/Hale522520/p/10617228.html
Copyright © 2011-2022 走看看