码迷,mamicode.com
首页 > 其他好文 > 详细

Hdu 1381 Crazy Search

时间:2015-02-09 00:44:07      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:

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;
	}
}

 

Hdu 1381 Crazy Search

标签:

原文地址:http://www.cnblogs.com/Emerald/p/4280714.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!