题目意思: 给定两组单词,现在有一个组合单词的方法是把第二组中的每一个都加到第一组每一个单词的后面,求组合后总共的单词数。
解题思路: 先让我喷喷,尼玛看看这句什么意思"Youcan assume that the strings are formed by lower case letters (‘a’ to‘z’) only, that they are less than10 characters long and that each string is presented in one linewithout any leading or trailing spaces" ,你说它不是说了只由小写字母组成吗,它特么竟然会有空格作为输出,我靠足足WA了不下15次,搞不懂出题人是干嘛的。
言归正传,求解这一题有两种思路
1 set
我们知道set会里面的元素是不会有重复的,这样就可以直接舍去那么重复的单词了,我么只要把组合成的单词前部插入set,
最后输出set的元素个数即可,但是set 的效率很低我用了2.876接近TLE了,建议不要采用虽然代码简洁。
2 hash
哈希在查找这方面具有高效性,我们知道哈希表的原理是将一个单词转化为对应的哈希值h,然后把这个h作为数组的下标,数组存储的则是当前是第几个单词。
那么对于这一题,我么可以这么做,就是每组和成一个单词,我么都去判断当前单词是否在哈希表中,如果没有那么我么将它插入哈希表中,当前的个数加1,一直这么做到结束即可,最后输出个数ans
注意地方:
但是这一题有空格作为输入,所以比较恶心,
还有看看以下的样列空格用‘_’代替
1
3 3
a
b
_
a
_
c
对于这一组输入,我么来列举一下所有情况:
1 aa 2 a_ 3 ac 4 ba 5 b_ 6 bc 7 _a 8 __ 9 _c 答案输出的是8 那么我们就可以知道,题目把a_ 和 _a看成了相同, 所以我们在处理组合的时候对于空格的处理使用注意一下:如果两个都是空格那么直接另组合后的字符串为“ ” , 如果只有一个为空格, 那么忽视这个空格 , 组合后的单词直接为另外一个即可。
1 hash 代码:
#include <algorithm> #include <iostream> #include <cstring> #include <string> #include <vector> #include <cstdio> #include <stack> #include <queue> #include <set> using namespace std; #define MAXN 1000003 typedef string Str; Str Allstr[MAXN]; Str str1[MAXN]; Str str2[MAXN]; int head[MAXN] , next[MAXN]; int ans , cnt; //初始化哈希表 void init_table(){ ans = 0 , cnt = 1; memset(head , 0 , sizeof(head)); memset(next , 0 , sizeof(next)); } //哈希函数 int Hash(string str){ int seed = 131; int hash = 0; for(int i = 0 ; i < str.size() ; i++) hash = hash*seed + str[i]; return (hash & 0x7FFFFFFF) % MAXN; } //哈希表的插入 int insert_table(int s){ int h = Hash(Allstr[s]); int u = head[h]; while(u){ if(Allstr[u] == Allstr[s]) return 0;//如果之前有出现过那么直接返回0 u = next[u]; } //否则插入到链表中 next[s] = head[h];//链表往回移动一位 head[h] = s;//更新表头 return 1; } int main(){ //freopen("input.txt" , "r" , stdin); int t; scanf("%d" , &t); int i , j , k; int m ,n; char ch[100]; string str; for(i = 1 ; i <= t ; i++){ init_table(); scanf("%d%d" , &m , &n) ; getchar() ; for(j = 0 ; j < m ; j++){ gets(ch) ; str1[j] = ""; if(ch[0] != '\0'){ for(int g = 0 ; g < strlen(ch) ; g++) str1[j] += ch[g]; } else str1[j] = " "; } for(k = 0 ; k < n ; k++){ gets(ch) ; str2[k] = ""; if(ch[0] != '\0'){ for(int g = 0 ; g < strlen(ch) ; g++) str2[k] += ch[g]; } else str2[k] = " "; } //组合单词 for(j = 0 ; j < m ; j++){ for(k = 0 ; k < n ; k++){ if(str1[j] != " " && str2[k] != " ") str = str1[j] + str2[k]; if(str1[j] != " " && str2[k] == " ") str = str1[j]; if(str1[j] == " " && str2[k] != " ") str = str2[k]; if(str1[j] == " " && str2[k] == " ") str = " "; Allstr[cnt] = str; if(insert_table(cnt)) ans++; //如果插入成功ans++ cnt++;//注意要加加 } } printf("Case %d: %d\n" , i , ans); } return 0; }
2 set 代码
#include <algorithm> #include <iostream> #include <cstring> #include <string> #include <vector> #include <cstdio> #include <stack> #include <queue> #include <set> using namespace std; #define MAXN 1510 string str1[MAXN]; string str2[MAXN]; string str; set<string>s; int main(){ //freopen("input.txt" , "r" , stdin); int t; scanf("%d" , &t); int i , j , k; int m ,n; char ch[100]; for(i = 1 ; i <= t ; i++){ scanf("%d%d" , &m , &n) ; getchar() ; s.clear(); for(j = 0 ; j < m ; j++){ gets(ch) ; str1[j] = ""; if(ch[0] != '\0'){ for(int g = 0 ; g < strlen(ch) ; g++) str1[j] += ch[g]; } else str1[j] = " "; } for(k = 0 ; k < n ; k++){ gets(ch) ; str2[k] = ""; if(ch[0] != '\0'){ for(int g = 0 ; g < strlen(ch) ; g++) str2[k] += ch[g]; } else str2[k] = " "; } for(j = 0 ; j < m ; j++){ for(k = 0 ; k < n ; k++){ if(str1[j] != " " && str2[k] != " ") str = str1[j] + str2[k]; if(str1[j] != " " && str2[k] == " ") str = str1[j]; if(str1[j] == " " && str2[k] != " ") str = str2[k]; if(str1[j] == " " && str2[k] == " ") str = " "; s.insert(str); } } printf("Case %d: %d\n" , i , s.size()); } return 0; }