题目链接:https://loj.ac/problem/2823
描述:
给定一个字符串S ,先将字符串 S 复制一次(变成双倍快乐),得到字符串 T,然后在U中插入一个字符,得到字符串U 。
给出字符串U ,重新构造出字符串 S。
所有字符串只包含大写英文字母。
输入格式
第一行一个整数 ,表示字符串 U 的长度。
第二行一个长度为 n 的字符串,表示字符串U 。
输出格式
一行一个字符串S,表示字符串 。
特别地:
- 如果字符串无法按照上述方法构造出来,输出
NOT POSSIBLE
; - 如果字符串 不唯一,输出
NOT UNIQUE
。
样例
样例输入 1
7
ABXCABC
样例输出 1
ABC
样例输入 2
6
ABCDEF
样例输出 2
NOT POSSIBLE
样例输入 3
9
ABABABABA
样例输出 3
NOT UNIQUE
分析:进制hash模板,枚举被添加的是哪一位,用hash判断两段是否相等,注意not unique是不同的串s,不是所插字符的位置不同。
[l,r]的hash值
ll get(int l,int r){
return (h[r]-h[l-1]*p[r-l+1]%md1+md1)%md1;
}
[l,r]删去x的hash值
ll query(int l,int r,int x){
return (get(l,x-1)*p[r-x]%md1+get(x+1,r))%md1;
}
hash更多应用:
作者:henry_y
链接:https://blog.nowcoder.net/n/39e7cbeeec014e63800a553fdc1e4e5c
来源:牛客网
#include<bits/stdc++.h>
#define N 1000010
#define ll long long
using namespace std;
char s[N*2];
ll h[N*2],p[N*2];
const int md1=1e9+7,md2=1e9+9,base=2333;
ll get(int l,int r){
if(l>r)return 0;
return (h[r]-h[l-1]*p[r-l+1]%md1+md1)%md1;
}
ll query(int l,int r,int x){
return (get(l,x-1)*p[r-x]%md1+get(x+1,r))%md1;
}
int n;
map<ll,int>ma;
int main(){
scanf("%d",&n);
scanf("%s",s+1);
if(n%2==0){
printf("NOT POSSIBLE");return 0;
}
p[0]=1;h[0]=0;
for(int i=1;i<=n;i++)h[i]=(h[i-1]*base%md1+s[i])%md1,p[i]=p[i-1]*base%md1;
int ans=0,id;
for(int i=1;i<=n;i++){
if(i<=n/2+1&&query(1,n/2+1,i)==get(n/2+2,n)){
if(!ma.count(get(n/2+2,n))){
ans++;id=i;ma[get(n/2+2,n)]=1;
}
}
if(i>n/2+1&&get(1,n/2)==query(n/2+1,n,i)){
if(!ma.count(get(1,n/2))){
ans++;id=i;ma[get(1,n/2)]=1;
}
}
}
if(ans==0)printf("NOT POSSIBLE");
else if(ans==1){
int t=0;
for(int i=1;i<=n;i++){
if(i!=id&&t<n/2)printf("%c",s[i]),t++;
}
}
else printf("NOT UNIQUE");
return 0;
}