一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对,如abc和cba。

本文介绍了一种通过哈希表来解决大规模文件中寻找相反字符串对的问题。利用自定义哈希函数,将字符串及其反转后的形式散列存储,从而高效地找到配对。此方法适用于处理包含大量短字符串的数据集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件的大小上限是10G,不可能在内存操作了。考虑设计一种hash使得如果两个字符串维相反串能得出相同的hash值,然后用该hash将文件中的字符串散列到不同的文件中,再在各文件中进行匹配。比如这样的hash函数对字符串上所有字符的ascii求和,因为长度在1K以内,因此范围在int之内。更进一步,可以在上面那个hash后面再加一个字符串长度,可以得到更好的散列效果。

 

/************************************************************************/
/* 一个文件,内含一千万行字符串,每个字符串在1K以内,
   要求找出所有相反的串对,如abc和cba。
   思路:使用hash表
                                                                     */
/************************************************************************/



#include<iostream>
#include<string>
#include<malloc.h>
#include<stdlib.h>
#include<fstream>
using namespace std;

#define  ERROR 0

struct _LinkList//哈希表拉链结构
{
    char *strValue;
    _LinkList *next;
};
void Reverse(char str[],int len)//字符串反转函数,对字符串进行反转时,要使用数据表示字符串
{
    int start,end;
    start=0;
    end=len-1;
    while(start<end)
    {
        char temp;
        temp=str[start];
        str[start]=str[end];
        str[end]=temp;

        start++;
        end--;
    }
    
}
class CHash
{
private:
    _LinkList *List[350];//根据哈希地址构造拉链式哈希表
public:
    CHash();
    ~CHash();
    int HashFunc(char *str);
    void InitHash();
};
CHash::CHash()
{
    int i;
    for(i=0;i<320;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 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=mod*2;
        sum=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 *newNode,*head;
            newNode=(_LinkList*)malloc(sizeof(_LinkList));//新建一个结点
            if(!newNode)
                exit(ERROR);
            newNode->next=NULL;
            newNode->strValue=new char[10];        
            strcpy(newNode->strValue,str);//结点赋值
            
            head=List[addr];
            strcpy(tempstr,str);//保存下原始字符串
            Reverse(str,strlen(str));//将字符串反转
         
            while(head->next)//遍历哈希表拉链
            {
                head=head->next;                 
                
                if(strcmp(str,head->strValue)==0)//如果读入的字符串反转后与链表中字符串相等,则输出
                {    
                    cout<<head->strValue<<" "<<tempstr<<endl;
                    isRight=true;//标志位,字符串已处理
                    break;
                }

                
            }
            if(!isRight)//如果读入的字符串反转后与链表中字符串不相等,则将新结点插入到链表中
            {
                head->next=newNode;
                head=newNode;
                head->next=NULL;
            }

        }
    }
    fin.clear();
    fin.close();
}
int main()
{
    CHash CH=CHash();    
    CH.InitHash();
    return 1;
}

程序中为了验证方便,在文件字符串设定长度为5;

 

STL的set用什么实现的?为什么不用hash?

是用红黑树实现的,红黑树是一种平衡性很好的二分查找树。要使用hash的话,就需要为不同的存储类型编写哈希函数,这样就照顾不到容器的模板性了,而是用红黑树只需要为不同类型重载operator<就可以了。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值