zoukankan      html  css  js  c++  java
  • 洛谷 P1381 单词背诵 解题报告

    P1381 单词背诵

    题目描述

    灵梦有(n)个单词想要背,但她想通过一篇文章中的一段来记住这些单词。

    文章由(m)个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。

    输入输出格式

    输入格式:

    第1行一个数(n)

    接下来(n)行每行是一个长度不超过10的字符串,表示一个要背的单词。

    接着是一个数(m)

    然后是(m)行长度不超过10的字符串,每个表示文章中的一个单词。

    输出格式:

    输出文件共2行。第1行为文章中最多包含的要背的单词数,第2行表示在文章中包含最多要背单词的最短的连续段的长度。


    首先看懂题,要先把出现的所有单词都背了才能再找最小连续。

    所以第一目的是先做匹配找到有多少单词出现了。

    (hash)(map)几种方法。不过我比较毒瘤,写了字典树匹配。

    存下(f[i])数组表示文章第(i)个单词是字典中的第几个单词。

    第二步就是我也说不清楚的一个思想了,可能有单调队列的影子。

    我们先固定左端点l,扫描右端点直到包含所有出现的单词至少一次。

    用桶存下每个单词出现次数,然后边移动右端点边尝试移动左端点(如果加入右端点后出现次数大于1即可移动左端点)

    我犯的智障错误:

    1. 字典树居然减了'0',真是绝了。。。
    2. 统计时不小心把0给统计了。。。

    code:

    #include <cstdio>
    #include <cstring>
    int min(int x,int y) {return x<y?x:y;}
    const int N=1010;
    const int M=100010;
    const int inf=0x3f3f3f3f;
    struct node
    {
        int son[26],cnt;
    }t[N*10];
    char word[12];
    int cnt=0,n,m,f[M];
    void build(int j)
    {
        scanf("%s",word);
        int now=0,len=strlen(word);
        for(int i=0;i<len;i++)
        {
            int k=word[i]-'a';
            if(t[now].son[k])
                now=t[now].son[k];
            else
            {
                t[now].son[k]=++cnt;
                now=cnt;
            }
        }
        t[now].cnt=j;
    }
    void check(int j)
    {
        scanf("%s",word);
        int len=strlen(word),now=0;
        for(int i=0;i<len;i++)
        {
            int k=word[i]-'a';
            if(t[now].son[k])
                now=t[now].son[k];
            else
                return;
        }
        f[j]=t[now].cnt;
    }
    int cnt0[N],used[N],l,a,b=inf,a0=0;//要背长度,最短连续段长度
    void DP()
    {
        used[0]=1;
        for(int i=1;i<=m;i++)
        {
            if(!used[f[i]])
            {
                a0++;
                used[f[i]]=1;
            }
        }
        printf("%d
    ",a0);
        if(a0==0) {printf("0
    ");return;}
        l=1;
        memset(used,0,sizeof(used));
        used[0]=1;
        for(int i=1;i<=m;i++)
        {
            cnt0[f[i]]++;
            while(cnt0[f[l]]>1)
            {
                cnt0[f[l]]--;
                l++;
            }
            if(!used[f[i]])
            {
                a++;
                used[f[i]]=1;
            }
            if(a==a0)
                b=min(i+1-l,b);
        }
        printf("%d
    ",b);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            build(i);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            check(i);
        DP();
        return 0;
    }
    
    

    2018.6.3

  • 相关阅读:
    python socket 网络编程
    Python中的MySQL接口:PyMySQL & MySQLdb
    Docker Day1 & 2
    Java数据结构与算法(5):AVL树
    Solr集群环境搭建
    Java数据结构与算法(4):二叉查找树
    Solr单机环境搭建及部署
    Java数据结构与算法(3):队列
    Java数据结构与算法(2):栈
    Java数据结构与算法(1):线性表
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9130275.html
Copyright © 2011-2022 走看看