• 洛谷 P1381 单词背诵 题解


    题目

    其实这题跟hash没什么关系,直接用队列做就可以了(时间复杂度还过得去)。

    需要预处理的信息:文章中每个单词对应相同的要背的单词(下标)

    这里我先将要背的单词排序,然后二分(lower_bound)查找提高效率(打乱顺序不影响结果)

    然后从1到m遍历文章中的单词

    要做的事情如下:

    1、将当前的下标加入队列,并更新最优解(最多单词数)

    2、不难看出:如果队首的元素在队列中已经出现多次(>1),将队首删除答案更优(多余的数)

    3、更新最小长度(如果这个单词之前未出现,直接赋值为队列长度,否则与自身取min值)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int n, m, ans, minl, now, p[100005], vis[1005]; 
    //vis记录出现次数,p表示文章中每个词对应的要背的词 
    string s, str[1005];
    int main() {
    	scanf ("%d", &n);
    	for (register int i = 1; i <= n; ++i)  cin >> str[i];
    	sort (str + 1, str + n + 1);
    	scanf ("%d", &m);
    	for (register int i = 1; i <= m; ++i) {
    		cin >> s;
    		int t = lower_bound (str + 1, str + n + 1, s) - str;   //二分查找对应的词 
    		if (str[t] == s)  p[i] = t; 
    	}
    	queue <int> q;  vis[0] = 1e9;   //0表示没有对应的词,方便处理赋为极大值 
    	for (register int i = 1; i <= m; ++i) {
    		int k(0);     //k标记当前答案是否有更新 
    		if (!vis[p[i]]) k = 1, ans++;
    		q.push(i), vis[p[i]]++;
    		int t = q.front();
    		while (vis[p[t]] > 1 and q.size()) --vis[p[t]], q.pop(), t = q.front();   //删除队首多余的数 
    		int tmp = q.size();
    		if (k)  minl = tmp;
    		else minl = min (minl, tmp);   //如果答案有更新,直接赋值为队列长度,否则与自身取min值 
    	}
    	printf ("%d
    %d", ans, minl);
    	return 0;
    }
    

      

  • 相关阅读:
    实现类莫名的错误解决
    xml文件不识别dubbo标签,添加支持的方法
    不要粗心马虎,不然你要付出几倍的精力纠错
    redis 缓存功能摘要
    spring的maven工程(服务层和表现层分离)配置浅析
    暂时放弃dubbo
    Maven工程的JDK版本配置
    spring的SOA聚合工程应用框架的搭建
    阿里云用宝塔面板安装JDK、zookeeper、dubbo
    maven项目不能正常运行
  • 原文地址:https://www.cnblogs.com/whx666/p/11409650.html
Copyright © 2020-2023  润新知