题意翻译
一个名为"Berlanddesk"的电子邮件系统即将在Berland上线运营。该电子邮件系统的管理员希望整个系统的建设可以尽早完成,因此他们找到了资深程序员您,希望您能够为他们开发一个用户注册系统的原型产品。
该系统的运行遵循以下原则:
新用户注册时,他将向系统发送一则内容为其用户名的请求,如果该用户名尚未存在于系统数据库内,则将该用户名插入数据库,同时用户得到回应信息"OK"表示其已经成功注册。如果用户请求的用户名已经存在于数据库内,那么系统将产生一个新的用户名并将其加入数据库。新用户名由用户请求的用户名与正整数i构成,i为使"用户名i"尚未存在于数据库内的最小的i。
输入格式
第一行一个整数n(1<=n<=10^5)。接下来n行,每行表示用户向系统发出的一则请求。每行内容均非空且均为由至多32个小写拉丁字母组成的字符串。
输出格式
n行,每行表示系统对一则请求做出的回应。如果该用户名尚未存在于系统数据库内,则输出"OK"。如果用户请求的用户名已经被注册,则输出依照规则生成的新用户名。
输入输出样例
输入样例#1
4
abacaba
acaba
abacaba
acab
输出样例#1
OK
OK
abacaba1
OK
输入样例#2
6
first
first
second
second
third
third
输出样例#2
OK
first1
OK
second1
OK
third1
思路
法1:暴力枚举法。提交的时候要么第16个点TLE,要么第23个点TLE。
边输入边进行判断,如果未找到则输出“OK”并存储,如果找到就看他有几个,进行+1后输出。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int n,i,j,k(0);
string name;
bool flag=0;
string check[100001]={};
int cnum[100001]={};
cin>>n;
for(i=1;i<=n;i++)
{
cin>>name;
flag=0;
for(j=0;j<=k;j++)
{
if(name==check[j])
{
cnum[j]++;
cout<<check[j]<<cnum[j]<<endl;
flag=1;
break;
}
}
if(flag==0)
{
printf("OK\n");
}
check[k++]=name;
}
return 0;
}
法2:运用C++ STL中的map映射。我也不是太懂map,所以这个思路是洛谷大佬的。
- 建立
map<string,int>m;
, 从字符串映射到整数. - 插入
m[str]=key;
, str为字符串, key为映射到的整数. - 迭代器
map<string,int>::iterator it;
, 迭代器相当于是指针(或者说是一种数据类型). - 查询字符串是否存在
it=find(str)
, it为对应元素的迭代器. - 通过迭代器获取元素的整数值
int key=it->second
, first 是对应的string, second 是对应的字符串.(map中的元素为pair)
这样我们就可以将字符串插入map, 不重复, 每个字符串对应的那个整数就是我们记录这个字符串出现几次的数组的对应下标。
#include <map>
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
map<string,int> m;
int num[100005];//字符串出现几次
int main()
{
int n,i;
string str;
scanf("%d",&n);
map<string,int>::iterator it;//迭代器
for(i=1;i<=n;++i)
{
cin>>str;
it=m.find(str);//是否出现
if(it==m.end())
{
m[str]=i;
printf("OK\n");
}
else
{
int s=it->second;//在数组num中位置
num[s]++;
cout<<str<<num[s]<<endl;
}
}
return 0;
}