【题解】 #2823「BalticOI 2014 Day 1」三个朋友
Description:
一个字符串s,把他收尾相接一次,再在这个新字符串里插入一个字符,求原来的字符串是什么?
Sample Input:
7
ABXCABC
Sample Output:
ABC
Hint:
特别的对于找不到的输出NOT POSSIBLE。
对于不止一个输出NOT UNIQUE
1<=n<=2000001
Solution:
喵的,这题卡的真的很久。。。
弄得我都去颓bat了。。。
其实我们可以利用哈希的灵动性,求出一段哈希值。
于是枚举插入了那个字符,然后对左右两边的哈希值判断。
当然也得考虑一下我们的那个插入字符可能在中点旁边,这个时候哈希值得特殊处理一下。
unique 判断贼尖儿麻烦。。。WA了无数次。。。
#include<bits/stdc++.h>
using namespace std;
int n,ans;
const int N=2e6+5;
const int BASE=233,P=998244353;
int f[N],Pow[N],bac[30];
char a[N];
inline int sum(int l,int r){
if(l>r) return 0;
return ((f[r]-(1ll*f[l-1]*Pow[r-l+1])%P)%P+P)%P;
}
inline void Hash(int f[],const char str[]){
int len=strlen(str+1);
for(int i=1;i<=len;++i)
f[i]=((1ll*f[i-1]*BASE)%P+(int)str[i]-'A'+1)%P;
}
inline bool query(int now){
int Pre=0,Nxt=0;
if(now==(n+1)/2){
Pre=f[now-1];
Nxt=sum(now+1,n);
return Pre==Nxt;
}
if(now<(n+1)/2){
Pre=((1ll*f[now-1]*Pow[(n+1)/2-now])%P+sum(now+1,(n+1)/2))%P;
Nxt=sum((n+1)/2+1,n);
return Pre==Nxt;
}
if(now>(n+1)/2){
Pre=f[(n+1)/2-1];
Nxt=((1ll*sum((n+1)/2,now-1)*Pow[n-now])%P+sum(now+1,n))%P;
return Pre==Nxt;
}
return false;
}
int main(){
memset(bac,-1,sizeof(bac));
bool flag=false;
scanf("%d",&n);
scanf("%s",a+1);
Hash(f,a);
Pow[0]=1;
for(int i=1;i<=n;++i)
Pow[i]=(1ll*Pow[i-1]*BASE)%P;
for(int i=1;i<=n;++i)
if(query(i)){
ans++;
if(bac[a[i]-'A'+1]!=-1 && bac[a[i]-'A'+1]!=i-1) flag=true;
bac[a[i]-'A'+1]=i;
}
if(flag && ans>1) return puts("NOT UNIQUE"),0;
if(ans<1) return puts("NOT POSSIBLE"),0;
for(int i=1;i<=n;++i)
if(query(i)){
if(i==(n+1)/2){
for(int j=1;j<=i-1;++j) putchar(a[j]);
putchar('\n');
return 0;
continue;
}
if(i<(n+1)/2){
for(int j=1;j<=i-1;++j) putchar(a[j]);
for(int j=i+1;j<=(n+1)/2;++j) putchar(a[j]);
putchar('\n');
return 0;
continue;
}
if(i>(n+1)/2){
for(int j=(n+1)/2;j<=i-1;++j) putchar(a[j]);
for(int j=i+1;j<=n;++j) putchar(a[j]);
putchar('\n');
return 0;
continue;
}
}
return 0;
}