【bzoj3916】【Baltic2014】【friends】【hash】

Description

有三个好朋友喜欢在一起玩游戏,A君写下一个字符串S,B君将其复制一遍得到T,C君在T的任意位置(包括首尾)插入一个字符得到U.现在你得到了U,请你找出S.

Input

第一行一个数N,表示U的长度.
第二行一个字符串U,保证U由大写字母组成

Output

输出一行,若S不存在,输出"NOT POSSIBLE".若S不唯一,输出"NOT UNIQUE".否则输出S.

Sample Input

Sample Input1:
7
ABXCABC


Sample Input2:

6
ABCDEF

Sample Input3:

9
ABABABABA

Sample Output

Sample Output1:

ABC

Sample Output2:

NOT POSSIBLE

Sample Output3:

NOT UNIQUE

HINT

对于100%的数据 2<=N<=2000001
题解:
         随便hash,注意细节.
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#define P 107
#define N 2000010
#define ull unsigned long long
using namespace std;
ull h[N],t[N];
int n,ans,len;
map<ull,int>q;
char ch[N];
int main(){
  scanf("%d",&n);
  if (n%2==0||n==1){puts("NOT POSSIBLE");return 0;}
  len=(n-1)/2;
  scanf("%s",ch+1);
  t[0]=1;h[0]=0;
  for (int i=1;i<=n;i++) t[i]=t[i-1]*P;
  for (int i=1;i<=n;i++) h[i]=h[i-1]*P+(ull)ch[i];
  //for (int i=1;i<=n;i++) cout<<h[i]<<endl;
  for (int i=1;i<=n;i++){
    if (i<=len){
      ull l=h[i-1],mid=h[len+1]-t[len+1-i]*h[i],r=h[n]-h[n-len]*t[len];
      //cout<<l<<' '<<mid<<' '<<r<<endl;
      l=l*t[len-i+1]+mid;
      if (l==r){
        if (q[l]||(!ans)) ans=i,q[l]=1;
        else {puts("NOT UNIQUE");return 0;}
      }
    }
    if (i==len+1){
      ull l=h[i-1],r=h[n]-t[len]*h[i];
      if (l==r){
        if (q[l]||(!ans)) ans=i,q[l]=1;
        else {puts("NOT UNIQUE");return 0;}
      } 
    }
    if (i>len+1){
      ull l=h[len],mid=h[i-1]-h[len]*t[i-1-len],r=h[n]-h[i]*t[n-i];
      r=mid*t[n-i]+r; 
      if (l==r){
        if (q[l]||(!ans)) ans=i,q[l]=1;
        else {puts("NOT UNIQUE");return 0;}
      } 
    }
  }
  if (!ans){puts("NOT POSSIBLE");return 0;}
  else{
    int t=1;
    while (len--){
      if (t==ans) t=t+1;
      printf("%c",ch[t]);
      t++;
    }
  }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值