Hankerrank World CodeSprint #4 Gridland Provinces (字符串双hash )

题目链接:https://www.hackerrank.com/contests/june-world-codesprint/challenges/gridland-provinces

题意:一个两行n列的字符格子,一个人必须走个哈密顿路径,任选起始和结束位置,最后求走出的字符串有多个不同的。

n<=1000


Observe that since the knight always completes his journey in minimum total time, he never visits the same city twice. In other words, the path formed by the Knight is a  path.


Suppose the knight starts his journey from cell , visits every cell to its  and comes to cell , then visits cell  and every cell to its  to cell . Now there are two possible options for the knight if he wishes to visit each cell  .


  • He can move  to cell , visiting all cells in between, and then go up to cell . From there visit all cells to its  until it reaches cell  thereby completing the tour.


  • Otherwise the knight can move to cell  followed by a move to cell . In this case there are again two possible options for the knight. Move from cell  to cell  followed by a move to cell  and have two choices again. Or visit all cells to its , move  and visit all remaining cells to its .


Note that the knight can start from cell  instead of cell . Also, the knight can start from column , visit every cell to its , move down/up and visit every cell to its  until it reaches column  again and repeat the same procedure with two choices as elaborated before. So we need to handle these cases as well with a similar strategy as described.


There are  different values for . For each value of , the simulation described above can be done in . The hash value of the final string can be calculated in  after some pre-processing. The number of   possible is then the number of    found overall which can be easily maintained with a hashset or a sorted array to remove duplicates. Overall complexity is  with a sorted array or  with a hashset.


和官方题解思路一样,因为可以DP求出不同串的hash值,只需要O(1),所以一共有O(N* N)个串,最后std::unique()去重一下就好了。

吐槽一下,数据真强啊,单hash被卡了,双hash第一次 写,两个素数模数取的不好也会被卡,我取的1e9+7和1e9+9


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
#include <string>
#include <cmath>
#include <set>
#include <map>
using namespace std;

#define REP(i, a, b) for (int i = (a), i##_end_ = (b); i < i##_end_; ++i)
#define MP make_pair
#define PB push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()
#define X first
#define Y second
template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;
typedef pair<LL, LL> pii;
const int oo = 0x3f3f3f3f;

const int N = 600 * 4 + 10;
pii h[N];
int top;
LL mp[N * N * 4];
int all;
char s[2][N];
const int MOD = 1e9 + 7;
const int MOD2 = 1e9 + 9;
const LL BASE = 26;
pair<LL, LL> p[N];

int main() {
	p[0].X = 1;
	for(int i = 1; i <= N - 10; i ++) p[i].X = p[i - 1].X * BASE % MOD;
	p[0].Y = 1;
	for(int i = 1; i <= N - 10; i ++) p[i].Y = p[i - 1].Y * BASE % MOD2;
	int T;
	cin >> T;
	while(T --) {
		int n;
		cin >> n;
		scanf("%s", s[0] + 1);
		scanf("%s", s[1] + 1);
		all = 0;
		int now = 0;
		top = 0;
		for(int i = 1; i <= n; i ++, now ^= 1) {
			pii tmp = pii(0, 0), nhash = pii(0, 0);
			if(now) {
				tmp.X = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD;
				tmp.Y = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;

			}
			else {
				tmp.X = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD;
				tmp.Y = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				h[j].X = (p[(i - 2) * 2].X * tmp.X + h[j].X) % MOD;
				h[j].Y = (p[(i - 2) * 2].Y * tmp.Y + h[j].Y) % MOD2;
			}
			h[++ top] = nhash;
			pii cur = pii(0, 0);
			if(now) {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
			}
			else {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				pii nowhash = pii( (p[(i - 1) * 2].X * cur.X + h[j].X) % MOD, (p[(i - 1) * 2].Y * cur.Y + h[j].Y) % MOD2);
			   	mp[++ all] = (nowhash.X << 32) | nowhash.Y;
			}
		}

		now = 1;
		top = 0;
		for(int i = 1; i <= n; i ++, now ^= 1) {
			pii tmp = pii(0, 0), nhash = pii(0, 0);
			if(now) {
				tmp.X = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD;
				tmp.Y = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;

			}
			else {
				tmp.X = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD;
				tmp.Y = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				h[j].X = (p[(i - 2) * 2].X * tmp.X + h[j].X) % MOD;
				h[j].Y = (p[(i - 2) * 2].Y * tmp.Y + h[j].Y) % MOD2;
			}
			h[++ top] = nhash;
			pii cur = pii(0, 0);
			if(now) {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
			}
			else {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				pii nowhash = pii( (p[(i - 1) * 2].X * cur.X + h[j].X) % MOD, (p[(i - 1) * 2].Y * cur.Y + h[j].Y) % MOD2);
			   	mp[++ all] = (nowhash.X << 32) | nowhash.Y;
			}
		}

		for(int i = 1; i <= n / 2; i ++) swap(s[0][i], s[0][n - i + 1]), swap(s[1][i], s[1][n - i + 1]);

		now = 0;
		top = 0;
		for(int i = 1; i <= n; i ++, now ^= 1) {
			pii tmp = pii(0, 0), nhash = pii(0, 0);
			if(now) {
				tmp.X = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD;
				tmp.Y = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;

			}
			else {
				tmp.X = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD;
				tmp.Y = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				h[j].X = (p[(i - 2) * 2].X * tmp.X + h[j].X) % MOD;
				h[j].Y = (p[(i - 2) * 2].Y * tmp.Y + h[j].Y) % MOD2;
			}
			h[++ top] = nhash;
			pii cur = pii(0, 0);
			if(now) {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
			}
			else {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				pii nowhash = pii( (p[(i - 1) * 2].X * cur.X + h[j].X) % MOD, (p[(i - 1) * 2].Y * cur.Y + h[j].Y) % MOD2);
			   	mp[++ all] = (nowhash.X << 32) | nowhash.Y;
			}
		}
		now = 1;
		top = 0;
		for(int i = 1; i <= n; i ++, now ^= 1) {
			pii tmp = pii(0, 0), nhash = pii(0, 0);
			if(now) {
				tmp.X = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD;
				tmp.Y = (s[0][i - 1] * BASE + s[1][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;

			}
			else {
				tmp.X = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD;
				tmp.Y = (s[1][i - 1] * BASE + s[0][i - 1]) % MOD2;
				for(int j = i - 1; j >= 1; j --) nhash.X = (nhash.X * BASE + s[1][j]) % MOD;
				for(int j = 1; j <= i - 1; j ++) nhash.X = (nhash.X * BASE + s[0][j]) % MOD;
				for(int j = i - 1; j >= 1; j --) nhash.Y = (nhash.Y * BASE + s[1][j]) % MOD2;
				for(int j = 1; j <= i - 1; j ++) nhash.Y = (nhash.Y * BASE + s[0][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				h[j].X = (p[(i - 2) * 2].X * tmp.X + h[j].X) % MOD;
				h[j].Y = (p[(i - 2) * 2].Y * tmp.Y + h[j].Y) % MOD2;
			}
			h[++ top] = nhash;
			pii cur = pii(0, 0);
			if(now) {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
			}
			else {
				for(int j = i; j <= n; j ++) cur.X = (cur.X * BASE + s[0][j]) % MOD;
				for(int j = n; j >= i; j --) cur.X = (cur.X * BASE + s[1][j]) % MOD;
				for(int j = i; j <= n; j ++) cur.Y = (cur.Y * BASE + s[0][j]) % MOD2;
				for(int j = n; j >= i; j --) cur.Y = (cur.Y * BASE + s[1][j]) % MOD2;
			}
			for(int j = 1; j <= top; j ++) {
				pii nowhash = pii( (p[(i - 1) * 2].X * cur.X + h[j].X) % MOD, (p[(i - 1) * 2].Y * cur.Y + h[j].Y) % MOD2);
			   	mp[++ all] = (nowhash.X << 32) | nowhash.Y;
			}
		}
		sort(mp + 1, mp + 1 + all);
		int ans = unique(mp + 1, mp + 1 + all) - (mp + 1);
		printf("%d\n", ans);

	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值