DestinHistoire

 

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)    收藏  举报

导航