1353: PIPI的字符串问题V(字符串哈希)

题目描述

PIPI叕来考查大家字符串处理能力了~
PIPI一开始有一个字符串S,现在它把S扩充了一倍得到了T,然后顽皮的POPO又在T中的某一个位置(可以是任意位置)插入了某一个字符得到了字符串P。
现在给你P,你需要找到初始的字符串S。
如果S不存在,输出NOT POSSIBLE
如果S不唯一,输出NOT UNIQUE
如果S唯一,输出字符串S

输入

单组数据。
第一行给出字符串P。|P|<=2e6.仅包含大写字母。

输出

输出占一行,按题目要求输出答案。

样例输入

ABXCABC

样例输出

ABC

#include <bits/stdc++.h>
using namespace std;
const int N=2e6+5;
typedef unsigned long long ull;
const ull base=23333;
ull hs[N],pw[N]; ///hs记录哈希数组的值 pw记录base进制的值
char s[N];
ull gethash(int l,int r)
{
    return hs[r]-hs[l-1]*pw[r-l+1];///求长度从l到r的哈希值
}
int main()
{
    scanf("%s",s+1); ///字符串从下标1开始存储
    int n=strlen(s+1),mid=n/2+1;
    ull last=0; ///last记录上一个位置的哈希值
    int ans=0,pos=0;///pos记录断点的位置
    if(n%2==0) {printf("NOT POSSIBLE\n");return 0;}
    pw[0]=1;
    for(int i=1;i<=n;i++)
    {
        pw[i]=pw[i-1]*base;
        hs[i]=hs[i-1]*base+s[i]-'A'+1;
    }
    for(int i=1;i<=n;i++)
    {
        ull A,B,C; ///将整个字符串分为三段 断点在前半部分 中间 后半部分时
        if(i<mid)
        {
            A=gethash(1,i-1);
            B=gethash(i+1,mid);
            C=gethash(mid+1,n);
            if(A*pw[mid-i]+B==C&&last!=C) pos=i,ans++,last=C;
        }
        else if(i>mid)
        {
            A=gethash(1,mid-1);
            B=gethash(mid,i-1);
            C=gethash(i+1,n);
            if(A==B*pw[n-i]+C&&last!=A) pos=i,ans++,last=A;
        }
        else
        {
            A=gethash(1,mid-1);
            B=gethash(mid+1,n);
            if(A==B&&last!=A) pos=i,ans++,last=A;
        }
        if(ans>1) break;
    }
    if(ans==0) printf("NOT POSSIBLE\n");
    else if(ans>1) printf("NOT UNIQUE\n");
    else
    {
        if(pos<=mid) for(int i=mid+1;i<=n;i++) printf("%c",s[i]);
        else
            for(int i=1;i<=mid-1;i++) printf("%c",s[i]);
    }
    return 0;
}

发布了78 篇原创文章 · 获赞 7 · 访问量 4579

猜你喜欢

转载自blog.csdn.net/weixin_44433678/article/details/104286363
今日推荐