【题目链接】
ybt 1401:机器翻译
ybt 1859:【10NOIP提高组】机器翻译
OpenJudge NOI 1.12 07:机器翻译
洛谷 P1540 [NOIP2010 提高组] 机器翻译
【题目考点】
1. 模拟
2. 队列
3. 循环数组
一个长为n的循环数组下标范围为0~n-1,n-1的下一个位置是0。循环数组取下一个位置的方法为:
i = (i + 1) % n
【题解代码】
解法1:用循环数组模拟内存
用一个布尔数组记录某单词是否存在于内存内。
内存变量mem为循环数组,初值设为-1,如果其值大于等于0,说明已经保存单词。如果找到下一个位置后,发现这个位置已经存在单词,那么这里就是需要被覆盖的“最早进入内存的那个单词”将其覆盖。并将该单词设为“不存在于内存”。
#include<bits/stdc++.h>
using namespace std;
bool hasWord[1005];//hasWord[i]:内存中是否有单词i
int mem[105], mi;//mem[i]:内存中第i位置的单词 mi:内存中刚刚保存单词的位置
int ct, m, n, word;//ct:计数
int main()
{
memset(mem, -1, sizeof(mem));//mem数组初值为-1,表示该位置没有保存单词。如果保存单词,值为非负整数。
cin >> m >> n;
for(int i = 0; i < n; ++i)
{
cin >> word;
if(hasWord[word] == false)//如果word单词不存在
{
hasWord[word] = true;//将word单词设为已经存在
mi = (mi + 1) % m;//mi取循环数组中的下一个位置
if(mem[mi] >= 0)//如果这个内存中的新位置mi已经有值了
hasWord[mem[mi]] = false;//把mi位置保存的单词mem[mi]设为不存在
mem[mi] = word;//内存中新位置保存单词word
ct++;//这种情况需要到外存查字典 计数加1
}
}
cout << ct;
return 0;
}
解法2:使用队列模拟
内存单词先进先出,符合队列的特点。可以用队列模拟。
#include<bits/stdc++.h>
using namespace std;
bool hasWord[1005];//hasWord[i]:内存中是否有单词i
queue<int> mem;//mem:内存
int ct, m, n, word;//ct:计数
int main()
{
cin >> m >> n;
for(int i = 1; i <= n; ++i)
{
cin >> word;
if(hasWord[word] == false)//如果word单词不存在
{
hasWord[word] = true;//将word单词设为已经存在
if(mem.size() == m)//如果已经存m个了
{
hasWord[mem.front()] = false;//队头单词设为不存在
mem.pop();//删除最早加入的单词 即队头出队
}
mem.push(word);//内存中保存新单词word
ct++;//这种情况需要到外存查字典 计数加1
}
}
cout << ct;
return 0;
}