程序能转,但是超时了,真是悲剧
先记录一下
/* *Input *输入数据分为名单和询问两部分。 *首先是名单部分,第一行是一个正整数 n (n<=500000), 表示名单中的人数。 下面 n 行, 每一行有一个由大写字母A-Z和小写字母a-z组成的字符串,代表名单中的姓名。 *然后是询问部分,第一行是一个正整数 m (m<=10000), 表示询问的次数。 下面 m 行, 每一行有一个由大写字母A-Z和小写字母a-z组成的字符串,代表要查询的姓名。 *输入中的每个字符串长度不超过10。 *Output *对于每一次查询,如果要查询的字符串出现在名单中输出 "YES", 否则输出 "NO"。(注意不要加引号) *每一次查询占一行。 */ // 考虑一下可以用基数排序 Radix Sort #include <stdio.h> #include <stdlib.h> int query(char* _string, char** record, int m) { int i; char *tmp_r,*tmp_s; for (i = 0 ; i < m ; ++i) { tmp_r = *(record+i); tmp_s = _string; while (*tmp_s != '/0' && *tmp_r != '/0' && *tmp_s == *tmp_r) {++tmp_s;++tmp_r;} if (*tmp_r == '/0' && *tmp_s == '/0') return 1; } return 0; } int main(void) { int i; int m,n; // m----> 成绩表 m----> 查询记录 char** record; char** enquire; scanf("%d", &m); record = (char**)calloc(m , sizeof(char*)); // 申请m个字符串 for (i = 0 ; i < m ; ++i) { *(record+i) = (char*)calloc(10 , sizeof(char)); scanf("%s",*(record+i)); // m+i 即是第i个char* } scanf("%d", &n); enquire = (char**)calloc(n , sizeof(char*)); // 申请m个字符串 for (i = 0 ; i < n ; ++i) { *(enquire+i) = (char*)calloc(10 , sizeof(char)); scanf("%s",*(enquire+i)); // m+i 即是第i个char* } for (i = 0 ; i < n ; ++i) { if (query(*(enquire+i) , record , m)) printf("YES/n"); else printf("NO/n"); } ////////////////////////////////////////////////////////////////////////// for (i = 0 ; i < m; ++i) { free(*(i+record)); } free(record); for (i = 0 ; i < n; ++i) { free(*(i+enquire)); } free(enquire); return 0; }
这个程序我在BUPT ACM上提交了9次,直到最后一次才成功,而且是网上看的别人的,惭愧==!
看来程序的超时不在于输入输出的超时,对于这个程序来说是算法的选择。
我只考虑了需要查找的值特别少的情况,但是对于大量的查找来说,查找算法是更重要的。我的查找属于一个一个的对比,数量小的时候无所谓了,但是当遇到了大量数据就傻逼了。
下面这个是我的程序中的另一个版本,将动态数组改成二维数组了。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_ARRAY 0x1f int main(void) { int i=0,j=0,flag=0; int m,n; // m----> 成绩表 n----> 查询记录 char record[MAX_ARRAY][MAX_ARRAY] = {'/0'}; // 初始化一个二维数组 char enquire[MAX_ARRAY][MAX_ARRAY] = {'/0'}; scanf("%d", &m); for (i = 0 ; i < m ; ++i) { scanf("%s",record[i]); } scanf("%d", &n); for (i = 0 ; i < n ; ++i) { scanf("%s",enquire[i]); } for (i = 0 ; i < n ; ++i) { for (j=0; j< m && !flag; ++j) { if (!strcmp(enquire[i],record[j])) { printf("YES/n");flag = 1;} } if(flag) { printf("NO/n");flag=0;} } return 0; }
最后这个是网上看的别人的,用到了ELF hash和qsort 学习
哈希+二分法
学了数据结构就要用,程序的分类 1.普通的小程序 2. 字符串程序 3. 需要数据结构和算法的程序(需要效率的)4. 需要数据结构和算法的程序(需要效率的)
#include <iostream> using namespace std; struct List{ char* name; int value; }; int ELFhash(char *key) { unsigned long h = 0; unsigned long g; while( *key ) { h =( h<< 4) + *key++; g = h & 0xf0000000L; if( g ) h ^= g >> 24;h &= ~g; } return h; } static List* list; static List* query; int cmp(const void *a, const void *b) { return list[*(int *)a].value >= list[*(int *)b].value ? 1 : -1; } int main(){ int num_list = 0, num_query = 0; scanf("%d", &num_list); int *pIndex = new int[num_list]; list = new List[num_list]; int i = 0, j = 0, k = 0; for(i = 0; i < num_list; i++) { list[i].name = (char *)malloc( sizeof(char) * 11 ); scanf("%s", list[i].name); pIndex[i] = i; list[i].value = ELFhash(list[i].name); } qsort(pIndex, num_list, sizeof(int), cmp); scanf("%d", &num_query); query = new List[num_query]; for(i = 0; i < num_query; i++) { query[i].name = (char *)malloc( sizeof(char) * 11 ); scanf("%s", query[i].name); query[i].value = ELFhash(query[i].name); } int low = 0, high = 0;int mid = 0; bool isFind = false; for(k = 0; k < num_query; k++) { isFind = false;low = 0;high = num_list - 1; while(low <= high){ mid = (low + high) / 2; if(list[ pIndex[mid] ].value == query[k].value) { // 如果两个value值是相同的 i = 0; j = mid; while( j > 0 && list[ pIndex[j-1] ].value == query[k].value){ //线性探测再散列?? i++;j--; } for(j = mid - i; j < num_list && list[ pIndex[j] ].value == query[k].value; j++) if(strcmp( list[ pIndex[j] ].name , query[k].name ) == 0){ // 键值相同的几个项再去比较 isFind = true; break; } break; } else if(list[ pIndex[mid] ].value > query[k].value){ high = mid - 1; } else{low = mid + 1; } } if(isFind)printf("YES/n"); else printf("NO/n"); } return 0; }