LOJ #2823. 「BalticOI 2014 Day 1」三個朋友
阿新 • • 發佈:2018-12-02
我稱原來的字串為子串,子串無疑只有兩種:前面或者後面
分類討論,列舉是前面還是後面,再列舉那個字母要去掉,用hash判斷(雙hash)
Q:如何用hash判斷呢?
A:用字首和和字尾和,然後組合一下,細節在程式碼中
Q:這就好了?
A:GG,注意:輸出NOT UNIQUE當且僅當兩個字串不一樣,而不是額外那個字母不一樣
#include<cstdio> #define ll long long const int p1=1e9+7,p2=1e7+7; using namespace std; const int N=2e6+5; int n; ll a1,a2,b1[N],b2[N],c1[N],c2[N],t1[N],t2[N]; char s[N]; bool ans,f; int main() { scanf("%d%s",&n,s+1); for(int i=1;i<=n>>1;i++) a1=(a1*1000+s[i])%p1,a2=(a2*1000+s[i])%p2; for(int i=(n>>1)+1;i<=n;i++) b1[i]=(b1[i-1]*1000+s[i])%p1,b2[i]=(b2[i-1]*1000+s[i])%p2; t1[n+1]=1,t2[n+1]=1; for(int i=n;i>=(n>>1)+1;i--) c1[i]=(c1[i+1]+s[i]*t1[i+1])%p1,c2[i]=(c2[i+1]+s[i]*t2[i+1])%p2, t1[i]=t1[i+1]*1000%p1,t2[i]=t2[i+1]*1000%p2; for(int i=(n>>1)+1;i<=n;i++) if((b1[i-1]*t1[i+1]+c1[i+1])%p1==a1) if((b2[i-1]*t2[i+1]+c2[i+1])%p2==a2) { ans=1; break; } if(ans) f=1,ans=0; a1=a2=0; for(int i=(n>>1)+2;i<=n;i++) a1=(a1*1000+s[i])%p1,a2=(a2*1000+s[i])%p2; for(int i=1;i<=(n>>1)+1;i++) b1[i]=(b1[i-1]*1000+s[i])%p1,b2[i]=(b2[i-1]*1000+s[i])%p2; t1[(n>>1)+2]=t2[(n>>1)+2]=1; c1[(n>>1)+2]=c2[(n>>1)+2]=0; for(int i=(n>>1)+1;i;i--) c1[i]=(c1[i+1]+s[i]*t1[i+1])%p1,c2[i]=(c2[i+1]+s[i]*t2[i+1])%p2, t1[i]=t1[i+1]*1000%p1,t2[i]=t2[i+1]*1000%p2; for(int i=1;i<=(n>>1)+1;i++) if((b1[i-1]*t1[i+1]+c1[i+1])%p1==a1) if((b2[i-1]*t2[i+1]+c2[i+1])%p2==a2) { ans=1; break; } if(ans&&f) { bool ff=0; for(int i=1;i<=n>>1;i++) if(s[i]!=s[i+(n>>1)+1]) { ff=1; break; } if(ff) puts("NOT UNIQUE"); else for(int i=1;i<=n>>1;i++) putchar(s[i]); }else if(ans||f) { if(f) for(int i=1;i<=n>>1;i++) putchar(s[i]); else for(int i=(n>>1)+2;i<=n;i++) putchar(s[i]); }else puts("NOT POSSIBLE"); return 0; }