[Ybt Advanced 2-2-1] String hash

String hash

Topic link: ybt efficient advanced 2-2-1

Topic

Given a bunch of strings, ask you how many are different.

Ideas

This question is obviously a hash.

We randomly get a number of values, and then have a hash value for each string.
(The hash value of the same string must be the same, and the hash value of different strings is generally different and may be the same)

Then we just use the string with his hash value in front to see if it is the same.

(As for recording which strings are in a hash value, I use the adjacency list that exists)

Code

#include<cstdio>
#include<cstring>
#define mo 19491001
#define ll long long

using namespace std;

struct node {
    
    
	int to, nxt;
}e[10001];
int n, ans, hash[19491010], size, KK, sizee;
ll hash_num, times;
char c[10001][1501];
bool yes, same;

void push(int x, int y) {
    
    //邻接表记录同一个hash值有哪些字符串
	e[++KK] = (node){
    
    y, hash[x]}; hash[x] = KK;
}

int main() {
    
    
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
    
    
		scanf("%s", c[i]);
		size = strlen(c[i]);
		
		hash_num = 0ll;
		times = 1ll;
		for (int j = 0; j < size; j++) {
    
    //得出hash值
			hash_num = (hash_num + (times * c[i][j]) % mo) % mo;
			times = (times * 307ll) % mo;
		}
		
		if (hash[hash_num]) {
    
    //之前有这个hash值,与哪些有这个值的字符串进行配对,看有没有出现过
			same = 0;
			for (int j = hash[hash_num]; j; j = e[i].nxt) {
    
    
				sizee = strlen(c[e[j].to]);
				if (size == sizee) {
    
    
					yes = 1;
					for (int k = 0; k < size; k++)
						if (c[i][k] != c[e[j].to][k]) {
    
    
							yes = 0;
							break;
						}
					if (yes) {
    
    //出现过
						same = 1;
						break;
					}
				}
			}
			if (!same) {
    
    //没有出现过,是新的字符串
				push(hash_num, i);
				ans++;
			}
		}
		else {
    
    //之前没有这个hash值,是新的字符串
			push(hash_num, i);
			ans++;
		}
	}
	
	printf("%d", ans);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/112900083