请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

算法超时

2:机器翻译

查看

提交

统计

提问

总时间限制: 

1000ms

 

内存限制: 

262144kB

描述

VariantF的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。
假设内存中有M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过M,软件会将新单词存入一个未使用的内存单元;若内存中已存入M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。
假设一篇英语文章的长度为N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

输入

第一行为两个正整数M 和N,代表内存容量和文章的长度。
第二行为N 个非负整数,按照文章的顺序,每个数(大小不超过1000000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。
对于50%的数据,1<=N、M<=1000;
对于100%的数据,1<=N、M<=1000000。

输出

一个整数,为软件需要查词典的次数。

样例输入

3 7
1 2 1 5 4 4 1

样例输出

5

提示

整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况:
空:内存初始状态为空。
1. 1:查找单词1 并调入内存。
2. 1 2:查找单词2 并调入内存。
3. 1 2:在内存中找到单词1。
4. 1 2 5:查找单词5 并调入内存。
5. 2 5 4:查找单词4 并调入内存替代单词1。
6. 2 5 4:在内存中找到单词4。
7. 5 4 1:查找单词1 并调入内存替代单词2。
共计查了5 次词典。

这个问题,我在网上找了好多答案都超时,我的答案也是,

我的代码是

#include<iostream>
#include<queue>
#include<set>
using namespace std;
int main() {
	int M, N;
	cin >> M >> N;
	int sum=0;
	queue<int> myq;
	set<int> myset;
	int temp;
	cin >> temp;
	int i;
	for (i = 0; i < N && myset.size()<M; i++) {
		if (myset.find(temp) == myset.end()) {	
			myq.push(temp);
			myset.insert(temp);
			sum += 1;
		}
		cin >> temp;
	}
	for (int j = i; j < N;j++) {
		if (myset.find(temp) == myset.end()) {
			myset.erase(myset.find(myq.front()));
			myq.pop();
			myq.push(temp);
			myset.insert(temp);
			sum += 1;
		}
		if(j<N-1)
		cin >> temp;
	}
	cout << sum;
	return 0;
}

您有什么好的解法吗

正在回答

1回答

抱歉,由于时间原因,在这个课程的问答区里,我不可能做到每个同学把平时各个地方遇到的算法问题贴到这里,我就开始给同学们解题。这个课程的问答区的提问以课程中的问题为主,扩展算法问题只限于leetcode中的问题。在其他地方遇到的问题,请在题目相应的讨论区和对应人群探讨交流,请谅解。


(以我的经验,你的思路没问题,题目可能在卡常数时间。给我题目提交链接我看一下。)


---


我的AC代码:

#include <cstdio>
#include <queue>
#include <cstring>

using namespace std;

int main() {
    
    int N, M;
    queue<int> q;
    bool mem[1000001];
    memset(mem, false, sizeof(mem));
    
    scanf("%d%d", &M, &N);
    int input, res = 0, t;
    while(N --){
        scanf("%d", &input);
        if(!mem[input]){
            mem[input] = true;
            q.push(input);
            if(q.size() > M){
                t = q.front();
                q.pop();
                mem[t] = false;
            }
            res ++;
        }
    }
    printf("%d\n", res);
    
    return 0;
}


1 回复 有任何疑惑可以回复我~
  • http://ysusoft.openjudge.cn/stackqueue/2/
    回复 有任何疑惑可以回复我~ 2018-03-01 08:43:45
  • 测了一下,你的程序从复杂度的角度,最需要修改的地方是把set(平衡二叉树,平均O(lgn)复杂度)换成哈希表(平均O(1)复杂度)。不过我使用unordered_set实验依然TLE,然后我就用bool数组代替哈希表;输入输出用scanf和printf(比cin,cout快),然后就过了。其实在正规比赛中,很少有卡这种用cin,cout不过,用scanf,printf却能过的情况。如果出现这种情况参赛选手会造反的...:)anyway,代码我附在上面了。
    回复 有任何疑惑可以回复我~ 2018-03-01 09:35:41
  • 非常感谢!
    回复 有任何疑惑可以回复我~ 2018-03-01 09:42:02
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号