问题 E: 【 哈希和哈希表】Three Friends
时间限制: 1 Sec 内存限制: 128 MB
提交: 30 解决: 4
[提交] [状态] [讨论版] [命题人:admin]
题目描述
Three friends like to play the following game. The first friend chooses a string S. Then the second friend constructs a new string T that consists of two copies of the string S. finally, the third friend inserts one letter at the beginning, the end or somewhere inside the string T, thereby creating a string U.
You are given the string U and your task is to reconstruct the original string S.
输入
The first line of the input contains N(2 ≤ N ≤ 2000001), the length of the final string U. The string U itself is given on the second line. It consists of N uppercase English letters (A, B, C, . . . , Z).
输出
Your program should print the original string S. However, there are two exceptions:
1.If the final string U could not have been created using the above procedure, you should print NOT POSSIBLE.
2.If the original string S is not unique, you should print NOT UNIQUE.
样例输入
7
ABXCABC
样例输出
ABC
第一个人选一个串s,第二个人将s复制,得到一个ss串,第三个人在串的任意位置加一个字符得到最终串u
现在给你u,让你求原始串s,如果有多个原始串s,输出NOT UNIQUE,如果求不出,输出NOT POSSIBLE
看样例,
第一个人选了ABC,第二个人变成ABCABC,第三个人在第一个B后面加个X
字符串hash,题目并不难,可我却读错了题,不唯一指的是多个不同的原式串s,而不是多种情况
例如aaa,则应该输出a,因为虽然有三种方式得到原始串s,但是原始串s是唯一的
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef pair<ull,ull> pull;
const int maxn = 2e6+7;
map<pull,bool> M;
const pull p{131LL,13331LL},one{1LL,1LL},zero{0LL,0LL};
pull operator - (pull a,pull b){return make_pair((a.first - b.first),(a.second - b.second));}
pull operator * (pull a,pull b){return make_pair((a.first * b.first),(a.second * b.second));}
pull operator + (pull a,pull b){return make_pair((a.first + b.first),(a.second + b.second));}
pull operator + (pull a,int b){return make_pair((a.first + b ),(a.second + b ));}
pull Pow(pull a,int n){
pull ans = one;
while(n){
if(n&1)ans = ans*a;
a = a*a;
n>>=1;
}
return ans;
}
pull Strcut(pull *Len,int l,int r){
return r<l?zero:Len[r] - Len[l-1]*Pow(p,r-l+1);
}
pull Splice(pull a,pull b,int n){
return (n < 0)?a:a*Pow(p,n)+b;
}
pull crups(pull *Len,int l,int r,int k){
if(k<l || k>r)
return Strcut(Len,l,r);
return Splice(Strcut(Len,l,k-1),Strcut(Len,k+1,r),r-(k+1) +1);
}
char a[maxn];
pull Len[maxn];
int main(){
int n;
scanf("%d",&n);
scanf("%s",a+1);
for(int i=1;i<=n;i++)
Len[i] = Len[i-1]*p + a[i];
int ansk = -1,flag = 0;
for(int k=1;k<=n;k++){
pull x = k< n/2+1?crups(Len,1,n/2+1,k):crups(Len,1,n/2,k);
pull y = k<=n/2+1?crups(Len,n/2+2,n,k):crups(Len,n/2+1,n,k);
if(x == y){
if(ansk != -1){
if(!M.count(x))
flag = 1;
}
ansk = k;
M[x] = 1;
}
}
if(ansk == -1)
printf("NOT POSSIBLE\n");
else if(flag)
printf("NOT UNIQUE\n");
else{
if(ansk<=n/2)for(int i=n/2+2;i<=n ;i++)printf("%c",a[i]);
else for(int i=1 ;i<=n/2;i++)printf("%c",a[i]);
printf("\n");
}
return 0;
}