P1540 [NOIP 2010 提高组] 机器翻译
P1540 [NOIP 2010 提高组] 机器翻译 解题思路与代码注释
解题思路
这道题目考察的是队列和缓存替换算法的应用,具体实现的是FIFO(先进先出)的缓存替换策略。
核心思路
-
使用一个队列来维护当前内存中的单词,队列长度不超过内存容量M
-
使用一个标记数组
vis来记录单词是否在内存中 -
对于每个新单词:
-
如果已经在内存中(
vis[x]为真),则不需要查词典 -
如果不在内存中:
-
查词典次数+1
-
将单词加入队列
-
如果队列已满(M个单词),则移除队首单词(最早进入的)
-
更新标记数组
-
-
代码注释(STL队列实现)
#include<bits/stdc++.h> using namespace std; int m,n; // m:内存容量 n:文章长度 int vis[1001]; // 标记数组,记录单词是否在内存中(0表示不在) queue<int> q; // 使用队列维护内存中的单词(FIFO) int ans; // 记录查词典的次数 int main() { cin >> m >> n; // 输入内存容量和文章长度 for(int i = 1; i <= n; i++) // 处理每个单词 { int x; cin >> x; // 读取当前单词 if(!vis[x]) // 如果单词不在内存中 { ans++; // 需要查词典 vis[x]++; // 标记为在内存中 q.push(x); // 加入队列 if(q.size() > m) // 如果内存已满 { int top = q.front(); q.pop(); // 移除最早进入的单词(队首) vis[top]--; // 更新标记 } } } cout << ans; // 输出总查词典次数 return 0; }
数组模拟队列实现
#include<bits/stdc++.h> using namespace std; int m,n; int vis[1001]; // 标记数组 int q[1001]; // 数组模拟队列 int head = 0, tail = 0; // 队首和队尾指针 int ans = 0; // 查词典次数 int main() { cin >> m >> n; for(int i = 1; i <= n; i++) { int x; cin >> x; if(!vis[x]) // 单词不在内存中 { ans++; // 查词典次数增加 vis[x] = 1; // 标记为存在 q[tail++] = x; // 入队 if(tail - head > m) // 如果超过内存容量 { vis[q[head]] = 0; // 移除最早单词的标记 head++; // 队首指针后移 } } } cout << ans; return 0; }
两种实现对比
-
STL队列实现:
-
优点:代码简洁,直接使用标准库提供的队列操作
-
缺点:隐藏了底层实现细节
-
-
数组模拟队列:
-
优点:更直观展示队列工作原理,便于理解
-
缺点:需要手动维护头尾指针
-
算法分析
-
时间复杂度:O(N),每个单词只处理一次
-
空间复杂度:O(M),队列最多存储M个单词
该算法完美模拟了FIFO缓存替换策略,是理解操作系统内存管理和缓存算法的经典例题。

浙公网安备 33010602011771号