2619 三个好朋友 (字符串Hash模板)

2619 三个好朋友

 

有三个好朋友喜欢在一起玩游戏,A君写下一个字符串S,B君将字符串S复制一遍得

到两个S拼接而成的字符串T,C君在T的任意位置(包括首尾)插入一个字符得到U.现在

你得到了U,请你找出S。

比如得到U串为ABABA。

那么S串有可能是AB,T串为ABAB,之后在最后一个位置插入A,得到ABABA。

S串还有可能是BA,T串为BABA,之后在第一个位置插入A,得到ABABA。

输入

第1行:一个数n,表示U的长度。(1<=n<=200000)
第2行:一个字符串U,保证U由大写字母组成。

输出

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

输入样例

7
ABXCABC

5
ABABA

5
ABCAABC

5
AVVAC

5
ABBAB

11
XOJECXPOJEC

11
BNEMNBNEMNN

输出样例

ABC
NOT UNIQUE
NOT POSSIBLE
NOT POSSIBLE
AB
XOJEC
BNEMN

思路:

         字符串Hash模板题,注意分情况讨论以及不熟悉的Hash计算过程。

代码实现:

#include<iostream>
#include<string.h>
#include<math.h>
#include<set>
#include<map>
#include<stdio.h>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
using namespace std;

const int N = 4e5 + 100;
const int M = 4e5 + 100;

char str[N];
int  n, ans;
ull  tmpl, tmpr, tmp_len;
ull  power[N], Hash[N];
set<ull>sc;

ull getHash(int l, int r) {
  if (l > r) return 0;
  return  Hash[r] - Hash[l - 1] * power[r - l + 1];
          //*****
}
void init(int n) {
  memset(Hash, 0, sizeof(Hash));
  memset(power, 0, sizeof(power));
  ans = 0;
  sc.clear();
  power[0] = 1;

  for (int i = 1; i <= n; i++) {
    Hash[i] = Hash[i - 1] * (ull)131 + (ull)(str[i] - 'A' + 1);
    power[i] = power[i - 1] * (ull)131;
  }
}
void sol(int n) {
  for(int i = 1; i <= n; i++) {
    tmp_len = 0;
    if (i == 1) {
      tmpl = getHash(2, (n - 1) / 2 + 1);
      tmpr = getHash((n - 1) / 2 + 2, n);
    } else if(i == n) {
      tmpl = getHash(1, (n - 1) / 2);
      tmpr = getHash((n - 1) / 2 + 1, n - 1);
    } else if (i == n / 2 + 1) {
      tmpl = getHash(1, i - 1);
      tmpr = getHash(i + 1, n);
    } else if (i <= n / 2) {
      tmp_len = n / 2 + 1 - i;
         //*********
      tmpl = getHash(1, i - 1) * power[tmp_len] + getHash(i + 1, n / 2 + 1);
      tmpr = getHash(n / 2 + 2, n);
    } else {
      tmp_len = n - i;
      tmpl = getHash(1, n / 2);
      tmpr = getHash(n / 2 + 1, i - 1) * power[tmp_len] + getHash(i + 1, n);
    }

    if (tmpl == tmpr) {
      sc.insert(tmpl);
      ans = i;
    }
  }
}
void mycout(int n) {
  if (sc.size() == 0) {
    puts ("NOT POSSIBLE");
  } else if (sc.size() > 1) {
    puts ("NOT UNIQUE");
  } else {
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
      if(ans == i) continue;
      printf("%c", str[i]);
      cnt ++;
      if (cnt == (n - 1) / 2) {
        puts("");
        break;
      }

    }
  }
}
int main () {

#ifdef MYHOME
  freopen("input.txt", "r", stdin);
#endif
  while (scanf("%d", & n) != EOF) {

    scanf("%s", str + 1);
    if (n % 2 == 0) {
      puts("NOT POSSIBLE");
      continue;
    }

    init(n);

    sol(n);

    mycout(n);

  }
  return 0;
}

THE END;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值