题意:
只有一组数据,数据量为20M
根据单词出现顺序输出出现次数..
思路:
3种方法:① map ② BKDR求hash值<hash表的线性再散列方法或者是链表形式>
map的方法因为数据量很大..容易超时
Tips:
※ BKDR求字符串hash值方法:


1 unsigned int BKDRHash(char *str) 2 { 3 unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. 4 unsigned int hash = 0; 5 6 while (*str) 7 { 8 hash = hash * seed + (*str++); 9 } 10 11 return (hash & 0x7FFFFFFF); 12 }
原创是byvoid大人~
※学到了一种存所有单词的最省空间方法..


1 char buf[MAX_SIZE];
2 char *sa[MAXN];
3 char *ch;
4 int cnt;
5 // 读入字符串
6 ch = buf;
7 while (EOF != scanf("%s", ch)) {
8 sa[cnt++] = ch;
9 ch += strlen(ch) + 1;
10 }
原创是黄老~
※ 以前用map的时候都是
if(map[str] == 0) map[str] = tot++;
count[map[str]]++;
这样..但是因为调用map其实很费时间..
所以改进为int tmp = map[str];
if(tmp != 0) count[tmp]++;
else {
map[str] = tot++;
count[tot-1] = 1;
}
※ 对于hash链表和BKDR求hash值方法~个人感觉可以不一起使用~
hash链表比线性再散列快..因为不管是插入新值还是查询的时候都比线性再散列比较次数少..但是BKDR已经可以很大程度的减少了冲突..所以重叠使用反而不如BKDR+线性再散列快..
※ ※ ※ 这里无法忽视的都是数据的存储问题..
数组的大小很难控制..
太大了程序要崩溃..太小了会越界~
所以代码是存在问题的..
在数组大小那里..仅仅因为数据弱而ac了..
解决方案可以是先把字符串读入并记录单词个数
然后根据单词个数为数组开内存..
而解决单词的问题就用黄老的单词缓存方法~
Code:


1 #include <stdio.h> 2 #include <map> 3 #include <string> 4 using namespace std; 5 6 map<string, int> m; 7 char arr[4000024]; 8 int cnt[100024]; 9 int main() 10 { 11 int tot = 1; 12 while(scanf("%s", arr) != EOF) { 13 int tt = m[arr]; 14 if(tt != 0) cnt[tt]++; 15 else { 16 m[arr] = tot++; 17 cnt[tot-1]++; 18 } 19 } 20 for(int i = 1; i < tot; ++i) 21 printf("%d\n", cnt[i]); 22 return 0; 23 }


1 #include <stdio.h> 2 #include <cstring> 3 using namespace std; 4 const int MAX_SIZE = 21000000; 5 const int MAXN = 3000; 6 7 struct Node 8 { 9 char *s; 10 Node *next; 11 int value; 12 }*hash[MAX_SIZE], *p; 13 14 unsigned int BKDRHash(char *str) { 15 unsigned int seed = 131; //31 131 1313 13131 131313 etc... 16 unsigned int hash = 0; 17 18 while(*str) hash = hash*seed + (*str++); 19 20 return (hash&0x7FFFFFFF); 21 } 22 23 char buf[MAX_SIZE]; 24 int cnt[180000]; 25 int tot; 26 char *ch; 27 unsigned int key; 28 29 int main() 30 { 31 bool flag; 32 ch = buf; 33 tot = 0; 34 for(int i = 0; i < MAXN; ++i) 35 hash[i] = NULL; 36 while(EOF != scanf("%s", ch)) { 37 flag = false; 38 key = BKDRHash(ch); 39 for(p = hash[key%MAXN]; p; p = p->next) 40 if(strcmp(p->s, ch) == 0) { 41 cnt[p->value]++; 42 flag = true; 43 } 44 if(!flag) { 45 Node *tmp = new Node; 46 tmp->s = ch; 47 tmp->value = tot++; 48 cnt[tot-1] = 1; 49 tmp->next = hash[key%MAXN]; 50 hash[key%MAXN] = tmp; 51 ch = ch+strlen(ch)+1; 52 } 53 } 54 for(int i = 0; i < tot; ++i) 55 printf("%d\n", cnt[i]); 56 return 0; 57 }


1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 const int maxn = 180000; 6 7 int BKDRHash(char *str) 8 { 9 int hash = 0; 10 while (*str) 11 { 12 hash = hash*31 + (*str++); 13 } 14 return (hash & 0x7FFFFFFF); 15 } 16 17 struct node 18 { 19 int count; 20 char *s; 21 }h[maxn]; 22 23 int num[maxn]={0}; 24 int tot = 0; 25 void hashinsert(char *str) 26 { 27 int val = BKDRHash(str)%maxn; 28 while (h[val].count != 0) 29 { 30 if (strcmp(h[val].s,str)==0) 31 { 32 h[val].count++; 33 break; 34 } 35 val = (val+1)%maxn; 36 } 37 if (h[val].count == 0) 38 { 39 int len = strlen(str); 40 h[val].s = (char*)malloc(sizeof(char)*(len+1)); 41 strcpy(h[val].s,str); 42 h[val].count++; 43 num[++tot] = val; 44 } 45 } 46 47 char ss[3000000]; 48 49 int main() 50 { 51 memset(h,0,sizeof(h)); 52 while (scanf("%s",ss)!=EOF) 53 { 54 hashinsert(ss); 55 } 56 int i; 57 for (i=1; i<=tot; i++) 58 printf("%d\n",h[num[i]].count); 59 return 0; 60 }
题目链接:
http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1618