原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3916
思路:首先字符串长度为偶数的肯定不行,直接输出。
将字符插入的位置分三种情况讨论:前面,中间,后面。求出两部分的hash值,判断是否相等。
注意:可能存在在不同位置插入字符,但分开后的两部分却一样的情况。所以要用一个值来记录上一次匹配成功的hash值。
求每一部分的hash值时注意头和尾这两个特殊位置。
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long ull;
char s[2000100];
ull hash[2000100],pw[2000100];
const int base=131;
ull gethash(int l,int r);
int main(){
int len;
scanf("%d%s",&len,s+1);
if (len%2==0){
printf("NOT POSSIBLE");
return 0;
}
pw[0]=1;
for (int i=1;i<=len;i++){
hash[i]=hash[i-1]*base+s[i]+'A'+1;
pw[i]=pw[i-1]*base;
}
ull x,y,bt;
int flag=0,det,mid=len/2;
for (int i=1;i<=len;i++){
if (i<=mid){
if (i==1){
x=gethash(2,mid+1);
}
else{
x=gethash(1,i-1)*pw[mid-i+1]+gethash(i+1,mid+1);
}
}
else{
x=gethash(1,mid);
}
if (i<=mid+1){
y=gethash(mid+2,len);
}
else if(i==len){
y=gethash(mid+1,len-1);
}
else{
y=gethash(mid+1,i-1)*pw[len-i]+gethash(i+1,len);
}
if (x==y){
if (flag&&bt!=x){
printf("NOT UNIQUE");
return 0;
}
flag=1;
bt=x;
det=i;
}
}
if (flag){
for (int i=1,m=1;m<=mid;i++){
if (i!=det){
printf("%c",s[i]);
m++;
}
}
}
else{
printf("NOT POSSIBLE");
}
return 0;
}
ull gethash(int l,int r){
return hash[r]-hash[l-1]*pw[r-l+1];
}