【BZOJ】3916: [Baltic2014]friends

http://www.lydsy.com/JudgeOnline/problem.php?id=3916

#include <bits/stdc++.h>

using namespace std;

int n, ans[3]; char s[2000005];

void work(int now) {

	int l=1, r=n-(n>>1); if(now<2) ++r; int flag=0; //printf("%d\n", now);

	for(int i=0, tot=n>>1; i<tot; ++i) {

		if(s[l]!=s[r]) { //printf("%d %d\n", l, r);

			if(now==0 || flag) { ans[now]=0; return; }

			if(now==1) ans[now]=l, ++l;

			if(now==2) ans[now]=r, ++r;

			flag=1;

			--i; continue;

		}

		++l; ++r;

	}

	if(!flag) ans[now]=n-(n>>1);

}

bool check(int x, int y) { if(ans[x]==0 || ans[y]==0 || ans[x]==ans[y]) return 1; return 0; }

int main() {

	scanf("%d%s", &n, s+1);

	if((n&1)==0) { puts("NOT POSSIBLE"); return 0; }

	for(int i=0; i<3; ++i) work(i);

	if(!ans[0] && !ans[1] && !ans[2]) { puts("NOT POSSIBLE"); return 0; }

	for(int i=0; i<3; ++i) for(int j=0; j<3; ++j) if(i!=j && !check(i, j)) { puts("NOT UNIQUE"); return 0; }

	int pos=0;

	for(int i=0; i<3; ++i) if(ans[i]) pos=ans[i]; //for(int i=0; i<3; ++i) printf("%d\n", ans[i]);

	for(int i=1, cnt=0; i<=n; ++i) {

		if(i==pos) continue;

		putchar(s[i]);

		if(++cnt==(n>>1)) break;

	}

	return 0;

}

  

显然能枚举这个点然后左右hash吧= =

可是这样可能会被卡+常数大..

我们考虑3种情况= =这个点在中点左边、在中点上、中点右边。

然后计算这三种情况的答案= =然后就行辣= =(比如如果在左边,那么我们在扫的时候允许左边错一个字符

你可能感兴趣的:(ZOJ)