zoukankan      html  css  js  c++  java
  • 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;
    	}
    }
    
  • 相关阅读:
    CSS媒体查询
    重新认识caniuse
    范仁义css3课程---40、box-sizing属性实例
    前端超级实用技巧---2、css、js兼容性查询网站can i use
    日常英语---200221(shrink)
    心得体悟帖---200221(方针:进可攻退可守的方式:先把不熟悉的知识点录)
    心得体悟帖---200221(本来二月份就到了三月之期的)
    心得体悟帖---200220(对不同的人,用不同的处理方式(这个你远远没有理解))
    java中的String.format使用
    android中的ellipsize设置(省略号的问题)
  • 原文地址:https://www.cnblogs.com/Emerald/p/4280714.html
Copyright © 2011-2022 走看看