一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对,如abc和cba。
2013-04-01 00:29
330 查看
现在已经是深夜了,再写个博就睡~
题目据说是百度的一道面试题,找了个网上的代码,自己跑了一遍。
分析如下:
文件的大小上限是10G,不可能在内存操作了。考虑设计一种hash使得如果两个字符串维相反串能得出相同的hash值,然后用该hash将文件中的字符串散列到不同的文件中,再在各文件中进行匹配。比如这样的hash函数对字符串上所有字符的ascii求和,因为长度在1K以内,因此范围在int之内。更进一步,可以在上面那个hash后面再加一个字符串长度,可以得到更好的散列效果。
题目据说是百度的一道面试题,找了个网上的代码,自己跑了一遍。
分析如下:
文件的大小上限是10G,不可能在内存操作了。考虑设计一种hash使得如果两个字符串维相反串能得出相同的hash值,然后用该hash将文件中的字符串散列到不同的文件中,再在各文件中进行匹配。比如这样的hash函数对字符串上所有字符的ascii求和,因为长度在1K以内,因此范围在int之内。更进一步,可以在上面那个hash后面再加一个字符串长度,可以得到更好的散列效果。
#include <iostream> #include <string> #include <malloc.h> #include <stdlib.h> #include <fstream> using namespace std; #define ERROR 0 struct _linkList //hash拉链结构。 { char* strValue; _linkList* next; }; void reverse(char* str, int len) { int start, end; start = 0; end = len-1; while(start < end) { char temp = str[start]; str[start] = str[end]; str[end] = temp; start++; end--; } } class CHash { _linkList* list[350]; //根据哈希地址构造拉链式哈希表 public: CHash(); ~CHash(); int HashFunc(char* str); void InitHash(); }; CHash::CHash() { int i; for (i = 0; i < 350; i++) { list[i] = (_linkList*)malloc(sizeof(_linkList)); if (!list[i]) { exit(ERROR); } list[i]->next = NULL; // list[i]->strValue = new char[10]; } } CHash::~CHash() { int i; for (i = 0; i < 350; i++) { // free(list[i]->strValue); free(list[i]); } } int CHash::HashFunc(char str[]) //哈希函数,将字符串各字符对90取模,取模值为偶数乘权重2,将各值相加作为哈希地址 { char* p = str; int sum = 0; while(*p != '\0') { int mod = (int)(*p)%90; if (mod % 2 == 0) { mod *= 2; } sum += mod; p++; } return sum; } void CHash::InitHash() { ifstream fin; ofstream fout; char str[10]; char tempstr[10]; fin.open("data.txt"); if (fin.is_open()) { while (fin>>str) { int addr = HashFunc(str); bool isRight = false; _linkList *head; head = list[addr]; strcpy(tempstr, str); reverse(tempstr, strlen(tempstr)); while (head->next != NULL) //遍历哈希表拉链 { head = head->next; if (strcmp(tempstr, head->strValue) == 0) { cout<<head->strValue<<" "<<str<<endl; //如果读入的字符串反转后与链表中字符串相等,则输出 isRight = true;//标志位,字符串已处理。此处标志位的处理要好好学习一下! break; } } if (!isRight) //如果读入的字符串反转后与链表中字符串不相等,则将新结点插入到链表中 { _linkList* newNode = (_linkList*)malloc(sizeof(_linkList)); newNode->strValue = new char[10]; strcpy(newNode->strValue, str); //之前用newNode->setValue = str;这样它们就共用一个地址,下次循环时,传入str的值就会将原来的strValue覆盖掉。 //字符串的赋值一般要用strcpy! newNode->next = NULL; head->next = newNode; //head = newNode; } } } fin.clear(); fin.close(); } int main() { CHash CH = CHash(); CH.InitHash(); return 1; }
相关文章推荐
- 一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对,如abc和cba。
- 一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对
- 一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对
- 给定一个文件每一行是字符串,找出所有的逆序对,比如abc和cba是逆序的对。
- 给定一个文件每一行是字符串,找出所有的逆序对,比如abc和cba是逆序的对。
- 写一个函数,输出字符串中字符的所有排序。(比如:abc acb bac bca cab cba )
- 输入一个字符串,要求输出字符串中字符所有的排列,例如输入"abc",得到"abc","acb","bca","bac","cab","cba"
- 给你一个字符串s和一个长度相同的单词列表。 找出s中所有子字符串的起始索引,这些字符串中的每个单词只是一个字符串,没有任何中介字符。
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
- 题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
- 给你一个字符串s和一个长度相同的单词列表。 找出s中所有子字符串的起始索引,这些字符串中的每个单词只是一个字符串,没有任何中介字符。
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 结果请按字母顺序输出。
- 今天大家做的一个比赛题:有6个文件,每个文件里大约200w整数,每行一个找出所有文件里最大的一个数字
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。C++
- 找出字符串的最长子串,要求子串的所有字符相同 例如:str ="sssddddabcdef" 则输出字串为:dddd
- 编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
- 找出一个字符串中所有的元音字母
- 一个替换某文件夹下的所有文件中特定字符串的小工具