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