【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种情况= =这个点在中点左边、在中点上、中点右边。

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

posted @ 2015-03-27 22:33  iwtwiioi  阅读(413)  评论(0编辑  收藏  举报