hash实在无爱。。。。。看的云里雾里的。。。。。。。
思路:
1. 计算出字符串的三个哈希值(一个用来确定位置,另外两个用来校验)
2. 察看哈希表中的这个位置
3. 哈希表中这个位置为空吗?如果为空,则肯定该字符串不存在,返回
4. 如果存在,则检查其他两个哈希值是否也匹配,如果匹配,则表示找到了该字符串,返回
5. 移到下一个位置,如果已经越界,则表示没有找到,返回
6. 看看是不是又回到了原来的位置,如果是,则返回没找到
7. 回到3
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;
}
}