【BZOJ3916/Baltic2014】friends

                               3916: [Baltic2014]friends

                                             Time Limit: 30 Sec  Memory Limit: 256 MB
                                                       Submit: 1082  Solved: 357

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

 

解析:

       枚举改变的位置的前一个位置,用字符串哈希判断即可。

 

代码:

#include <bits/stdc++.h>
#include <tr1/unordered_map>
using namespace std;
using namespace std::tr1;
 
const int Max=2000005;
int n,m,sum,len,pos;
int inv[132];
unsigned long long Pow[Max],Hash[Max];
char ch[Max];
unordered_map<long long,bool>v;
 
inline void pre()
{
    Pow[0]=1;
    for(int i=1;i<=n;i++)
    {
      Hash[i] = Hash[i-1] * 131 + (ch[i] - 'A' + 1);
      Pow[i] = Pow[i-1] * 131;
    }
}
 
inline unsigned long long calc1(unsigned long long  m)
{
    return Hash[m] * Pow[len-m] + Hash[len+1] - Hash[m+1] * Pow[len-m];
}
 
inline unsigned long long calc2(unsigned long long  m)
{
    return (Hash[m] - Hash[len] * Pow[m-len]) * Pow[n-m-1] + Hash[n] - Hash[m+1] * Pow[n-m-1];
}
 
int main()
{
    scanf("%d\n%s",&n,ch+1);
    if(!(n&1)) {cout<<"NOT POSSIBLE\n";return 0;}
    pre();
    len=(n-1)>>1;
    for(int i=0;i<n;i++)
    {
      unsigned long long a=0,b=0;
      if(i<len)
      {
        a=calc1(i);
        b=Hash[n] - Hash[n-len] * Pow[len];
      }
      else
      {
        a=Hash[len];
        b=calc2(i);
      }
      if(a==b && !v[a]) v[a]=1,sum++,pos=i+1;
    }
     
    if(!sum) {cout<<"NOT POSSIBLE\n";return 0;}
    int x=0; 
    if(sum==1)
    {
      for(int i=1;i<=n;i++)
      {
        if(i!=pos)
        {
          cout<<ch[i];
          x++;
        }
        if(x==len) break;
     }
    }
    else cout<<"NOT UNIQUE\n";
 
    return 0;
}

代码:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值