WHU 1622 (哈希)

题目链接:点击打开链接

题意:给一个环问能不能从某个地方切开变成一个回文串。

前几天跑武汉做的一个题目。正解是用回文串的算法求出最长回文串然后奇偶性瞎搞,

但是哈希显然可以搞。

每次枚举断点,只要正向哈希值和逆向哈希值一样就可以认为是回文,用前缀和优化一下

复杂度O(n)。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define maxn 66666
#define seed 131
typedef unsigned long long ull;

int n;
char a[maxn];
ull hash1, hash2;
ull pre[maxn], last[maxn];

ull f (char a) {
	return a-'a';
}
#define pow Pow
ull pow[maxn];

void init () {
	last[n-1] = f(a[n-1]);
	for (int i = n-2; i >= 0; i--) {
		last[i] = last[i+1]*seed+f(a[i]);
	}

	pre[0] = f(a[0]);
	for (int i = 1; i < n; i++) {
		pre[i] = pre[i-1]+pow[i]*f(a[i]);
	}
}

int main () {
	pow[0] = 1;
	for (int i = 1; i < maxn; i++) pow[i] = pow[i-1]*seed;
	while (cin >> a) {
		n = strlen (a);
		init ();
		hash1 = hash2 = 0;
		for (int i = 0; i < n; i++) {
			hash1 = hash1*seed + f (a[i]);
			hash2 = hash2 + f (a[i])*pow[i];
		}
		bool ok = 0;
		if (hash1 == hash2)
			ok = 1;
		for (int i = 1; i < n && (!ok); i++) {
			hash1 -= f(a[i-1])*pow[n-1];
			hash1 = hash1*seed+f (a[i-1]);
			
			hash2 = last[i]+pre[i-1]*pow[n-i];
			if (hash1 == hash2)
				ok = 1;
		}
		puts (ok ? "Yes" : "No");
	}
    return 0;
}
/*
aaaaaa
abcde
ababab
aaaaba
aabbaa
dzxzdcbbbbc
acc
*/


你可能感兴趣的:(WHU 1622 (哈希))