今天的第一个题目
从昨天写到了今天,题目的意思不难理解
我的第一次思路就是建立一个100*150的方阵,
第一行用来标记名字的第一个字母
第二行用来标记名字的第二个字母
比如说a,abc,abe
存放的情况就是:
就可以通过这样一个很简单的表来查找,判断重复就是用末尾的标记,为2就是重复
昨天我就是深深陷入这一种思路,但是就是找不到那里错了
最后睡觉的时候突然就想到,如果是ab和ba
形成的表格就是
但是你要查找aa的话也是成功的,但是实际上并没有这个人
所以今天早上起来又开始了奋斗第二个方案,字典树又称为前缀树
最开始我是想到了这个,但是觉得可能会比较复杂,而且从来没有打过,就没有尝试
思路就是建立一棵二叉树,每一个节点都是一个单词
使用题目中的例子来建立一棵字典树就是这样子的
a
b
c
ad
acd
具体就不介绍了
代码当然也写了,一百五六十行。结果超时
也在预料之中,最终在大佬的帮助下,知道了一个东西set
这个东西差不多就是自动给你创建一个这样的字典树,并且还是一个平衡树。
而且还能够查找
具体只需要用到其中的两个函数
insert和count
insert的作用就是创建,而count的作用就是查找是否存在
这样这程序就很简单了
#include<iostream>
#include<string.h>
#include<set>
using namespace std;
int main()
{
set<string>s1;
set<string>s2;
int n;
cin>>n;
getchar();
while(n--)
{
string data;
cin>>data;
s1.insert(data);
}
cin>>n;
getchar();
while(n--)
{
string data;
cin>>data;
if(s1.count(data))
{
if(s2.count(data))
{
cout<<"REPEAT"<<endl;
}
else
{
cout<<"OK"<<endl;
s2.insert(data);
}
}
else
{
cout<<"WRONG"<<endl;
}
}
}
其中为了辨别是否重复
我们需要定义两个set的变量,其中一个类似于花名册
另外一个类似于打钩,点过一次名就打一个勾,
如果存在于花名册并且打钩标记了,那么就是重复的了
其他的存在和不存在就很好辨别了
第二个题
这个题目是在好友的推荐下学习了map之后写出来的
题目要求是求A-B=C的数对的个数,但是我们稍作转换就可以变成A-C=B或者C+B=A都可以
通过这样的计算,我们就只需要在原数组中查找重复的次数就可以了
具体代码如下
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<int,long long>s;
long long n;
long long c;
cin>>n>>c;
long long data[200005];
for(int i=0;i<n;i++)
{
cin>>data[i];
s[data[i]]++;
data[i]-=c;
}
long long result=0;
for(int i=0;i<n;i++)
{
result+=s[data[i]];
}
cout<<result;
}
第三个题
其中的哈希算法有点类似于给门配钥匙。
通过一种自己设定的算法来配钥匙,不同的门钥匙也不同。
通过自己设定的算法,是存在一定的几率两扇不同的门出现了相同的钥匙,其中就要让他复杂化,使这种几率降低。
但是想这种算法太麻烦了。这个题目和前面的一个题目很想
最终也是用set搞定
代码如下
#include<iostream>
#include<set>
#include<string>
using namespace std;
int main()
{
set<string>s;
int n;
int count=0;
cin>>n;
while(n--)
{
string data;
cin>>data;
if(s.count(data)==0)
{
count++;
s.insert(data);
}
}
cout<<count;
}
只需要判断是否出现过,如果出现过就不做任何操作,如果没有出现过,就计数,并且记录
计数的结果就是最终结果