• 洛谷 P2353 背单词


    题目背景

    小明对英语一窍不通,令老师十分头疼。于是期末考试前夕,小明被逼着开始背单词……

    题目描述

    老师给了小明一篇长度为N的英语文章,然后让小明背M个单词。为了确保小明不会在背单词时睡着,老师会向他提Q个问题,每次老师随机选择一个区间L..R,小明要回答在这段文字中他背过的单词总共出现过多少次。

    输入输出格式

    输入格式:

    第一行两个整数M、Q如前所述。第二行为英语文章。接下来M行每行一个需要背的单词。接下来Q行每行一个询问,包含两个整数L、R(含端点),即给定的文字区间。

    输出格式:

    Q行,对每个询问输出一行表示答案。

    输入输出样例

    输入样例#1:
    3 3
    abcabcbc
    abc
    bc
    a
    1 3
    6 7
    1 8
    输出样例#1:
    3
    0
    7
    

    说明

    数据范围:

    对于30%的数据,1<=N<=10^3,1<=Q<=10^3

    对于60%的数据,1<=N<=10^5,1<=Q<=10^5

    对于100%的数据,1<=N<=10^6,1<=M<=10,1<=Q<=10^6,1<=每个单词的长度<=N,1<=L<=R<=N

    提示:数据较大,请大家尽量采取高效率的读入输出方法。

    正解 m次kmp 统计前缀和。

    不知为什么的错解:AC自动机,卡了90分钟 。不明白为什么,感觉挺对,也可能是我写得丑。

    每次询问取出x~y的子串 跑AC自动机,路过大神帮忙看一下。。(明知不会有大神路过,却依旧恬不知耻)..

    屠龙宝刀点击就送

    #include <ctype.h>
    #include <cstdio>
    
    const int N = 1e6+5;
    int que[N],num[N],cnt[N],trie[N][26],fail[N],n,Q,siz=1;
    char text[N],a[N];
    inline void ins(int k)
    {
        int p=1;
        for(char *q=a;*q;++q)
        {
            int id=*q-'a';
            if(!trie[p][id]) trie[p][id]=++siz;
            p=trie[p][id];
        }
        cnt[p]++;
        num[p]=k;
    }
    inline void Read(int &x)
    {
        register char ch=getchar();
        for(x=0;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    }
    void build()
    {
        for(int i=0;i<=25;i++) trie[0][i]=1;
        int l=0,r=0;
        que[++r]=1;
        for(int now=que[++l];l<=r;now=que[++l])
        {
            for(int i=0;i<=25;i++)
            {
                if(trie[now][i])
                {
                    if(now==1) fail[trie[now][i]]=1;
                    else
                    {
                        int tmp=fail[now];
                        for(;tmp;tmp=fail[tmp])
                        {
                            fail[trie[now][i]]=trie[tmp][i];
                            break;
                        }
                        if(!tmp) fail[trie[now][i]]=1;
                    }
                    que[++r]=trie[now][i]; 
                }
            }
        }
    }
    int query(int l,int r)
    {
        int p=1,ans=0;
        for(int i=l-1;i<r;++i)
        {
            int id=text[i]-'a';
            for(;!trie[p][id];p=fail[p]);
            if(!p) p=1;
            p=trie[p][id];
            int now=p;
            for(;now;now=fail[now])
                if(num[now]) ans+=cnt[now];
        }
        return ans;
    }
    int main()
    {
        Read(n);
        Read(Q);
        scanf("%s",text);
        for(int i=1;i<=n;++i)
        {
            scanf("%s",a);
            ins(i);
        }
        build();
        for(int x,y;Q--;)
        {
            Read(x);
            Read(y);
            printf("%d
    ",query(x,y));
        }
        return 0;
    }
    求说为什么错的AC自动机
    #include <cstring>
    #include <ctype.h>
    #include <cstdio>
    const int N = 1e6+5;
    inline void read(int &x)
    {
        register char ch=getchar();
        for(x=0;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    }
    int Len,n,Q,los[N],Next[N],sum[N][15];
    char text[N],word[N];
    void kmp(int k,int l)
    {
        int i=0,j=-1;
        Next[i]=j;
        for(;i<l;)
        {
            if(j==-1||word[i]==word[j]) i++,j++,Next[i]=j;
            else j=Next[j];
        }
        i=0,j=0;
        for(;i<Len&&j<l;)
        {
            if(j==-1||text[i]==word[j]) i++,j++;
            else j=Next[j];
            if(j==l) j=Next[j],sum[i][k]++;
            
        }
    }
    int main()
    {
        read(n);
        read(Q);
        scanf("%s",text);
        Len=strlen(text);
        for(int i=1;i<=n;++i)
        {
            scanf("%s",word);
            int len=strlen(word);
            kmp(i,len);
            los[i]=len;
        }
        for(int i=1;i<=Len;++i)
         for(int j=1;j<=n;++j)
         sum[i][j]+=sum[i-1][j];
        for(int x,y,ans;Q--;)
        {
            read(x);
            read(y);
            ans=0;
            for(int i=1;i<=n;i++)
            {
                if(x+los[i]-1<=y)
                    ans+=sum[y][i]-sum[x+los[i]-2][i];
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    使用MoveIt!配置软件包在RViz中进行机器人运动规划
    ROS之Movelt!的安装与使用
    使用OpenCV和imagezmq通过网络实时传输视频流 | live video streaming over network with opencv and imagezmq
    3个例子详解C++ 11 中push_back 和 emplace_back差异
    使用TensorRT对caffe和pytorch onnx版本的mnist模型进行fp32和fp16 推理 | tensorrt fp32 fp16 tutorial with caffe pytorch minist model
    python gui tkinter快速入门教程 | python tkinter tutorial
    使用OpenMP加快OpenCV图像处理性能 | speed up opencv image processing with openmp
    快速遍历OpenCV Mat图像数据的多种方法和性能分析 | opencv mat for loop
    windows 10 上源码编译OpenCV并支持CUDA | compile opencv with CUDA support on windows 10
    ubuntu 16.04源码编译OpenCV教程 | compile opencv on ubuntu 16.04
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7383247.html
Copyright © 2020-2023  润新知