uva10887

hash实在无爱。。。。。看的云里雾里的。。。。。。。
思路:
1. 计算出字符串的三个哈希值(一个用来确定位置,另外两个用来校验)
2. 察看哈希表中的这个位置
3. 哈希表中这个位置为空吗?如果为空,则肯定该字符串不存在,返回
4. 如果存在,则检查其他两个哈希值是否也匹配,如果匹配,则表示找到了该字符串,返回
5. 移到下一个位置,如果已经越界,则表示没有找到,返回
6. 看看是不是又回到了原来的位置,如果是,则返回没找到
7. 回到3 
三个hash值重复的可能性大约就很小很小了吧。。。。
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
using namespace std;
int cryptTable[0x500];
void prepareCryptTable()
{
    unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;
    for( index1 = 0; index1 < 0x100; index1++ )
    {
        for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 )
        {
            unsigned long temp1, temp2;
            seed = (seed * 125 + 3) % 0x2AAAAB;
            temp1 = (seed & 0xFFFF) << 0x10;
            seed = (seed * 125 + 3) % 0x2AAAAB;
            temp2 = (seed & 0xFFFF);
            cryptTable[index2] = ( temp1 | temp2 );
       }
   }
}
unsigned long HashString( const char *lpszFileName, unsigned long dwHashType )
{
    unsigned char *key  = (unsigned char *)lpszFileName;
    unsigned long seed1 = 0x7FED7FED;
    unsigned long seed2 = 0xEEEEEEEE;
    int ch;
    while( *key != 0 )
    {
        ch = toupper(*key++);

        seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
        seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
    }
    return seed1;
}
bool vis [10000000];
int num2 [10000000];
int num3 [10000000];
int main()
{
    prepareCryptTable();
    int T,t=0;
    cin>>T;
    while(T--)
    {
        memset(vis,false,sizeof(vis));
        memset(num2,0,sizeof(num2));
        memset(num3,0,sizeof(num3));
        int num_a,num_b;
        cin>>num_a>>num_b;
        getchar();
        string a[num_a],b[num_b];
        for(int i=0;i<num_a;i++)
            getline(cin,a[i]);
        for(int j=0;j<num_b;j++)
            getline(cin,b[j]);
        int sum=0;
        for(int i=0;i<num_a;i++)
            for(int j=0;j<num_b;j++)
        {
            string s=a[i]+b[j];
            unsigned long n1=HashString(s.c_str(),0)%10000000;
            unsigned long n2=HashString(s.c_str(),1)%10000000;
            unsigned long n3=HashString(s.c_str(),2)%10000000;
            if(vis[n1])
            {
                if(n2==num2[n1]&&n3==num3[n1])
                    continue;
                else
                {
                    bool exist=false;
                    int k;
                    for(k=n1+1;k<10000000&&vis[k]&&k!=n1;k++)
                        if(n2==num2[k]&&n3==num3[k])
                        {
                            exist=true;
                            break;
                        }
                        if(exist)
                            continue;
                        else
                            vis[k]=true,num2[k]=n2,num3[k]=n3,sum+=1;
                }
            }
            else
                vis[n1]=true,num2[n1]=n2,num3[n1]=n3,sum+=1;
        }
         cout << "Case " << ++t << ": " << sum << endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值