【BZOJ】3916: [Baltic2014]friends

时间:2022-01-07 10:09:50

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

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