BZOJ 3916 [Baltic2014]friends
【题解】
暴力枚举添加字符的位置,然后判断去掉这个位置的字符串是否有由两个相同的串拼接而成。本题的n的范围为200W,暴力判断会TLE,所以要使用哈希。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<map> 5 #define LL long long 6 #define N 2000010 7 #define rg register 8 #define base (107) 9 using namespace std; 10 int n,pos,cnt,mid,val; 11 LL h[N],pow[N]; 12 char s[N],s1[N],s2[N]; 13 map<int,int>u; 14 inline int read(){ 15 int k=0,f=1; char c=getchar(); 16 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 17 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 18 return k*f; 19 } 20 inline LL geth(int l,int r){ 21 if(r<l) return 0; 22 return h[r]-h[l-1]*pow[r-l+1]; 23 } 24 inline bool check(int x){ 25 int l1=x-1,l2=n-x; LL tmp=0,tmp2=0; 26 if(x==mid){ 27 tmp=geth(1,mid-1); tmp2=geth(mid+1,n); 28 } 29 else{ 30 if(x<mid) tmp=geth(1,x-1)*pow[mid-x]+geth(x+1,mid),tmp2=geth(mid+1,n); 31 else tmp=geth(1,mid-1),tmp2=geth(mid,x-1)*pow[n-x]+geth(x+1,n); 32 } 33 // printf("%d %lld %lld\n",x,tmp,tmp2); 34 val=tmp; 35 return tmp==tmp2; 36 } 37 int main(){ 38 n=read(); mid=n/2+1; 39 if(!(n&1)){puts("NOT POSSIBLE"); return 0;} 40 scanf("%s",s+1); 41 pow[0]=1; 42 for(rg int i=1;i<=n;i++) h[i]=h[i-1]*base+(int)s[i],pow[i]=pow[i-1]*base; 43 // for(rg int i=1;i<=n;i++) printf("%d ",h[i]); puts(""); 44 for(rg int i=1;i<=n;i++){ 45 if(check(i)){ 46 if(!u[val]) u[val]=1,cnt++,pos=i; 47 } 48 if(cnt>1) break; 49 } 50 if(!cnt) puts("NOT POSSIBLE"); 51 else{ 52 if(cnt>1) puts("NOT UNIQUE"); 53 else{ 54 int t=1,pointer=1; 55 while(t<=n/2){ 56 if(pointer==pos) pointer++; 57 else printf("%c",s[pointer++]),t++; 58 } 59 puts(""); 60 } 61 } 62 return 0; 63 }