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;
	}
}
时间: 2024-10-08 13:27:19

Hdu 1381 Crazy Search的相关文章

Crazy Search

poj1200:http://poj.org/problem?id=1200 题意:给你一个有m种字符串,求长度为n的连续子串由多少种. 题解:网上的代码都是hash,但是本人觉得hash有问题,就是n,m稍微大点,hash的值都会爆出int,无法开数组来记录该串是否被记录.可能数据弱,结果hash竟然A了 .正确的解法是用set来存,把所有的hash值放进set,set有去重效果,最后求一下set的大小.但是这样结果是T了.不知道这题怎么解.一下是第一种代码.于是换别的,trie树来搞. Cr

poj 1200 Crazy Search

题目: 链接:点击打开链接 题意: 输入n和nc,以及字符串s,输出长度为n的不同字串的个数. 算法: 思路: 用hash判重(hash值......),看了大牛的代码,对hash还是不甚理解.... 代码: #include<iostream> #include<cstring> #include<cstdio> #include<cstdio> using namespace std; #define MAXN 16000010 const int MA

HDU 3157 Crazy Circuits(有源汇上下界最小流)

HDU 3157 Crazy Circuits 题目链接 题意:一个电路板,上面有N个接线柱(标号1~N),还有两个电源接线柱 + -,给出一些线路,每个线路有一个下限值求一个可以让所有部件正常工作的总电流 没有则输出impossible 思路: 有源汇有上下界求最小流,建模方法为: 按无源汇先建图,跑超级源汇ss->tt一次,然后加入t->s,容量INF的边,在跑一次ss->tt,如果是满流,就有解,解为t->s边的当前流量 顺带写个最大流的,最大流就先把t->s加入直接跑

POJ 1200 Crazy Search(Hash)

Description Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could be finding a hidden prime number in a given text. Such number could be the number of different substrings of a given size that exist in t

HDU 2222 - Keywords Search

试个模板- - /* HDU 2222 - Keywords Search [ AC自动机 ] */ #include <bits/stdc++.h> using namespace std; const int N = 500005; const int SIZE = 26; struct Trie { int ch[N][SIZE]; int f[N], last[N], cnt[N], val[N]; int tot, ans; void init() { tot = 0; memset

POJ-1200 Crazy Search(hash)

Crazy Search Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 27336   Accepted: 7641 Description Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could be finding a hidden prime number in a gi

[poj1200]Crazy Search(hash)

Crazy Search Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 26713 Accepted: 7449 Description Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could be finding a hidden prime number in a given

HDU 2222 Keyword Search AC自动机模板

#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <io

POJ 1200 Crazy Search (字符串hash)

题目大意: 分析长度为n的子串有多少种. 思路分析: 对于没出现的字符,将其分配一个数字. 然后将子串看做一个nc进制的数. 然后hash判断. #include <cstdio> #include <iostream> #include <algorithm> #include <map> #include <cstring> #include <string> using namespace std; bool vis[26666