Hdu 1381 Crazy Search

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1381

 

此题可以用哈希数组求解,至于什么是哈希,可以先看以下这篇推荐文章,写得挺不错的。

推荐:http://www.cnblogs.com/yangecnu/p/Introduce-Hashtable.html#undefined

首先是求key值,我采取了,求余法。

key = value mod p

 

接着是确定value与p的值。

p的值根据可能的组合数进行确定。

而value的值,为采取了如下方法,假设子串长度为N,那么

int value = 0;

int tmp = 1;

for( int i=0; i<N; i++ ) {

	value = ( c[i]-'a'+1 ) * tmp;

	tmp = tmp << 1; // 等同于 tmp = tmp * 2

}

 也就是根据每个字符在子串出现的位置,乘以2的相应次方

 

我采用了“拉链法”(在推荐的资料中有介绍)避免冲突。

因为我用了new申请内存,所以有一些delete操作;不过不用delete也是可以ac的。

建议初始声明的数组不要过大,否则很容易超内存

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <string>



using namespace std;



typedef struct Node{

	char *part;

	Node *next;

}Node;



const int MUL_VALUE = 2;

const int LETTER_VALUE = 26 - 1; //设'a'为1, 'z'为26 

const int MAXN = 3000000;

Node hash[MAXN];



int prime[6] = {23, 673, 17573, 456959, 2999999}; // 素数

int arrayLimit;

string s;

int N, NC;



void SetArrayLimit( int &NC );

int GetKey( int value );

void InsertValue( int value, char *part );

int Query( Node* target );



int main() {

	int T;

	int i, j;

	int length;

	int value, tmp;

	char *part;

	while( cin >> T ) {

		while( T-- ) {

			scanf( "%d%d", &N, &NC );

			SetArrayLimit( NC );

			cin >> s;

			length = s.length();

			value = 0;

			tmp = 1;

			part = new char[N];

			for( i=0; i<N && i<length; i++ ) {

				value = value + (s[i]-LETTER_VALUE )*tmp;

				tmp = tmp << 1;

				part[i] = s[i];

			}

			InsertValue( value, part );

			for( i=N; i<length; i++ ) {

				value = 0;

				tmp = 1;

				for( j=0; j<N; j++ ) {

					value = value + ( s[ i-N+1+j ] - LETTER_VALUE )*tmp;

					tmp = tmp << 1;

					part[j] = s[ i-N+1+j ];

				}

				InsertValue( value, part );

			}

			int total = 0;

			for( i=0; i<arrayLimit; i++ ) {

				total += Query( hash[i].next );

				hash[i].next = NULL;

			}

			cout << total << endl;

			delete part;

		}

	}

	return 0;

}



void SetArrayLimit( int &NC ) { // 确立此次使用的数组上限

	int i=0;

	int tmp = 26;

	for( i=1; i<NC && tmp<=MAXN; i++ ) {

		tmp *= 26;

	}

	for( i=0; i<4; i++ ) {

		if( prime[i] >= tmp ) {

			break;

		}

	}

	arrayLimit = prime[i];

	return ;

}



int GetKey( int value ) { // 得到key值

	return value % arrayLimit;

}



void InsertValue( int value, char *part ) { // 插入值

	int key = GetKey( value );

	Node *target = &hash[key];

	while( target->next!=NULL ) {

		target = target->next;

		if( strcmp( target->part, part )==0  ) {

			return;

		}

	}

	Node *t = new Node;

	t->part = new char[N];

	strcpy( t->part, part );

	t->next = NULL;

	target -> next = t;

	return ;

}



int Query( Node* target ) {  // 递归求出结果,同时方便delete操作

	if( target == NULL ) {

		return 0;

	}

	else {

		int t = 1+Query( target->next );

		delete target -> part;

		delete target;

		return t;

	}

}

 

你可能感兴趣的:(search)