BZOJ-3916 [Baltic2014]friends(hash)
题目描述
第一个人写下一个字符串 \(S\),第二个人将其复制一遍得到 \(T\),第三个人在 \(T\) 的任意位置(包括首尾)插入一个字符得到 \(U\)。现在你得到了 \(U\),找出 \(S\)(\(2\leq |U|\leq 2\times 10^6\))。若 \(S\) 不存在,输出 NOT POSSIBLE。若 \(S\) 不唯一,输出 NOT UNIQUE,否则输出 \(S\)。
分析
子串 \(s[l,r]\) 的哈希值为 \(hash[r]-hash[l-1]\times pow[r-l+1]\)。
设中点为 \(mid=\frac{n+1}{2}\),枚举断点,断点的前面一段 \(+\) 后面一段等于完整的一段 $hash $ 值,要注意前面那一段需要乘 \(pow\),判断中点点两端的 \(hash\) 值。判重的时候,如果与前面有一样的答案,只算一个答案。除非是答案中的字符串不同,才算多重答案。如果不加判断,遇到 ABBAABA 这种数据就会输出 UNIQUE。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
const int BASE1=131;
const int BASE2=139;
char str[N+10],s[N+10];
int n,mid;
unsigned long long pow1[N+10],pow2[N+10];
unsigned long long hash1[N+10],hash2[N+10];
unsigned long long get(int op,int l,int r)
{
if(op==1)
return hash1[r]-hash1[l-1]*pow1[r-l+1];
if(op==2)
return hash2[r]-hash2[l-1]*pow2[r-l+1];
}
pair<unsigned long long,unsigned long long> HASH1,HASH2;
map<pair<unsigned long long,unsigned long long>,bool > mp;
int check(int pos)
{
if(pos<mid)
{
HASH1.first=get(1,1,pos-1)*pow1[mid-pos]+get(1,pos+1,mid);
HASH1.second=get(1,mid+1,n);
HASH2.first=get(2,1,pos-1)*pow2[mid-pos]+get(2,pos+1,mid);
HASH2.second=get(2,mid+1,n);
}
else if(pos>mid)
{
HASH1.first=get(1,1,mid-1);
HASH1.second=get(1,mid,pos-1)*pow1[n-pos]+get(1,pos+1,n);
HASH2.first=get(2,1,mid-1);
HASH2.second=get(2,mid,pos-1)*pow2[n-pos]+get(2,pos+1,n);
}
else if(pos==mid)
{
HASH1.first=get(1,1,mid-1);
HASH1.second=get(1,mid+1,n);
HASH2.first=get(2,1,mid-1);
HASH2.second=get(2,mid+1,n);
}
if(HASH1.first==HASH1.second&&HASH2.first==HASH2.second)
{
if(mp[make_pair(HASH1.first,HASH2.first)]==1)
return 0;
mp[make_pair(HASH1.first,HASH2.first)]=1;
int cnt=0;
if(pos<=mid)
{
for(int i=mid+1;i<=n;i++)
s[++cnt]=str[i];
}
else
{
for(int i=1;i<=mid-1;i++)
s[++cnt]=str[i];
}
return 1;
}
return 0;
}
int main()
{
cin>>n;
if(n%2==0)
{
puts("NOT POSSIBLE");
return 0;
}
scanf("%s",str+1);
pow1[0]=pow2[0]=1;
for(int i=1;i<=n;i++)
{
pow1[i]=pow1[i-1]*BASE1;
pow2[i]=pow2[i-1]*BASE2;
}
for(int i=1;i<=n;i++)
{
hash1[i]=hash1[i-1]*BASE1+str[i];
hash2[i]=hash2[i-1]*BASE2+str[i];
}
int ans=0;
mid=(n+1)/2;
for(int i=1;i<=n;i++)
{
ans=ans+check(i);
if(ans==2)
break;
}
if(ans==0)
puts("NOT POSSIBLE");
else if(ans==2)
puts("NOT UNIQUE");
else
puts(s+1);
return 0;
}
posted on 2020-11-18 10:34 DestinHistoire 阅读(145) 评论(0) 收藏 举报
浙公网安备 33010602011771号