20181031noip模拟赛T1
思路:
我们会发现不合法的位置只有两种情况
要么在前半边,要么在后半边
那么,我们将序列劈两次
使两次的长度分别为:
(n为偶数时要特判一下,因为根本不可能)
(n/2),(n/2+1)
(n/2+1),(n/2)
分别暴力贪心的匹配就好
但是,想ACACACACA这种,就会出锅
特判一下就好
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define rii register int i #define rij register int j #define p1 19260817 #define p2 998244353 using namespace std; int n,t; char ls[2000005]; int hash1() { long long ans=1; for(rii=1;i<=n/2;i++) { ans*=ls[i]; ans%=p1; } return ans; } int hash2() { long long ans=1; for(rii=1;i<=n/2;i++) { ans*=ls[i]; ans%=p2; } return ans; } int pash1() { long long ans=1; for(rii=(n+1)/2+1;i<=n;i++) { ans*=ls[i]; ans%=p1; } return ans; } int pash2() { long long ans=1; for(rii=(n+1)/2+1;i<=n;i++) { ans*=ls[i]; ans%=p2; } return ans; } void solve() { scanf("%d\n",&n); int cnt=0,wz=0; for(rii=1;i<=n;i++) { cnt++; ls[i]=getchar(); } scanf("\n"); if(n%2==0) { puts("NOT POSSIBLE"); return; } int dp=0; for(rii=1;i<=n-2;i++) { if(ls[i]!=ls[i+2]) { dp=1; break; } } if(dp==0) { puts("NOT UNIQUE"); return; } int bnt=n/2; int sl=0,pd=0; for(int i=1;i<=n/2;i++) { bnt++; if(ls[i]!=ls[bnt]) { bnt++; pd++; if(ls[bnt]!=ls[i]) { pd++; } } if(pd>=2) { break; } } int cs1=0,cs2=0; if(pd<=1) { sl++; cs1=hash1(); cs2=hash2(); wz=1; } pd=0,bnt=0; int kkk=(n+1)/2; for(int i=kkk+1;i<=n;i++) { bnt++; if(ls[bnt]!=ls[i]) { bnt++; pd++; if(ls[bnt]!=ls[i]) { pd++; } } if(pd>=2) { break; } } if(pd<=1) { sl++; wz=2; } if(sl==2) { if(cs1==pash1()&&cs2==pash2()) { sl--; } } if(sl==2) { puts("NOT UNIQUE"); } if(sl==0) { puts("NOT POSSIBLE"); } if(sl==1) { if(wz==1) { int ltt=n/2; for(rii=1;i<=ltt;i++) { putchar(ls[i]); } putchar(10); } else { int ltt=(n+1)/2; for(rii=ltt+1;i<=n;i++) { putchar(ls[i]); } putchar(10); } } } int main() { freopen("lgg.in","r",stdin); freopen("lgg.out","w",stdout); scanf("%d\n",&t); for(rii=1;i<=t;i++) { solve(); } return 0; }