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 }
View Code

 

posted @ 2018-08-10 21:07  Driver_Lao  阅读(219)  评论(0编辑  收藏  举报