【题解】 #2823「BalticOI 2014 Day 1」三个朋友

Description:

一个字符串s,把他收尾相接一次,再在这个新字符串里插入一个字符,求原来的字符串是什么?

Sample Input:

7

ABXCABC

Sample Output:

ABC

Hint:

特别的对于找不到的输出NOT POSSIBLE。
对于不止一个输出NOT UNIQUE
1<=n<=2000001

Solution:

喵的,这题卡的真的很久。。。

弄得我都去颓bat了。。。

其实我们可以利用哈希的灵动性,求出一段哈希值。

于是枚举插入了那个字符,然后对左右两边的哈希值判断。

当然也得考虑一下我们的那个插入字符可能在中点旁边,这个时候哈希值得特殊处理一下。

unique 判断贼尖儿麻烦。。。WA了无数次。。。

#include<bits/stdc++.h>
using namespace std;

int n,ans;
const int N=2e6+5;
const int BASE=233,P=998244353;
int f[N],Pow[N],bac[30];
char a[N];

inline int sum(int l,int r){
    if(l>r) return 0;
    return ((f[r]-(1ll*f[l-1]*Pow[r-l+1])%P)%P+P)%P;
}
inline void Hash(int f[],const char str[]){
    int len=strlen(str+1);
    for(int i=1;i<=len;++i)
        f[i]=((1ll*f[i-1]*BASE)%P+(int)str[i]-'A'+1)%P;
}
inline bool query(int now){
    int Pre=0,Nxt=0;
    if(now==(n+1)/2){
        Pre=f[now-1];
        Nxt=sum(now+1,n);
        return Pre==Nxt;
    }
    if(now<(n+1)/2){
        Pre=((1ll*f[now-1]*Pow[(n+1)/2-now])%P+sum(now+1,(n+1)/2))%P;
        Nxt=sum((n+1)/2+1,n);
        return Pre==Nxt;
    } 
    if(now>(n+1)/2){
        Pre=f[(n+1)/2-1];
        Nxt=((1ll*sum((n+1)/2,now-1)*Pow[n-now])%P+sum(now+1,n))%P;
        return Pre==Nxt;
    }
    return false;
}
int main(){
    memset(bac,-1,sizeof(bac));
    bool flag=false;
    scanf("%d",&n);
    scanf("%s",a+1);
    Hash(f,a);
    Pow[0]=1;
    for(int i=1;i<=n;++i)
        Pow[i]=(1ll*Pow[i-1]*BASE)%P;
    for(int i=1;i<=n;++i) 
        if(query(i)){
            ans++;
            if(bac[a[i]-'A'+1]!=-1 && bac[a[i]-'A'+1]!=i-1) flag=true;
            bac[a[i]-'A'+1]=i;
        }
    if(flag && ans>1) return puts("NOT UNIQUE"),0;
    if(ans<1) return puts("NOT POSSIBLE"),0;
    for(int i=1;i<=n;++i)
        if(query(i)){
            if(i==(n+1)/2){
                for(int j=1;j<=i-1;++j) putchar(a[j]);
                putchar('\n');
                return 0;
                continue;
            }
            if(i<(n+1)/2){
                for(int j=1;j<=i-1;++j) putchar(a[j]);
                for(int j=i+1;j<=(n+1)/2;++j) putchar(a[j]);
                putchar('\n');
                return 0;
                continue;
            }
            if(i>(n+1)/2){
                for(int j=(n+1)/2;j<=i-1;++j) putchar(a[j]);
                for(int j=i+1;j<=n;++j) putchar(a[j]);
                putchar('\n');
                return 0;
                continue;
            }
        }
    return 0;
}

转载于:https://www.cnblogs.com/JCNL666/p/10815934.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值