字符串哈希-friends-HYSBZ - 3916

字符串哈希-friends-HYSBZ - 3916

题意:

假 设 有 字 符 串 s 0 , 先 经 过 复 制 得 到 2 s 0 , 再 向 2 s 0 中 插 入 一 个 字 符 x , 得 到 字 符 串 s 。 假设有字符串s_0,先经过复制得到2s_0,再向2s_0中插入一个字符x,得到字符串s。 s0,2s0,2s0xs

现 在 给 定 s , 判 断 能 否 复 原 到 s 0 。 现在给定s,判断能否复原到s_0。 ss0

若 能 , 输 出 s 0 ; 若 有 多 种 方 案 , 输 出 : “ N O T     U N I Q U E ” ; 若 不 能 , 输 出 : “ N O T     P O S S I B L E ” 。 若能,输出s_0;\\若有多种方案,输出:“NOT \ \ \ UNIQUE”;\\若不能,输出:“NOT \ \ \ POSSIBLE”。 s0NOT   UNIQUE;NOT   POSSIBLE

样例:
Sample Input:

  S a m p l e    I n p u t 1 : 7 A B X C A B C   S a m p l e    I n p u t 2 : 6 A B C D E F   S a m p l e    I n p u t 3 : 9 A B A B A B A B A \\ \ \\Sample\ \ Input1: \\7 \\ABXCABC \\ \ \\Sample \ \ Input2: \\6 \\ABCDEF \\ \ \\Sample \ \ Input3: \\9 \\ABABABABA  Sample  Input1:7ABXCABC Sample  Input2:6ABCDEF Sample  Input3:9ABABABABA

Sample Output:

S a m p l e    O u t p u t 1 : A B C   S a m p l e    O u t p u t 2 : N O T    P O S S I B L E   S a m p l e    O u t p u t 3 : N O T    U N I Q U E \\Sample \ \ Output1: \\ABC \\ \ \\Sample \ \ Output2: \\NOT\ \ POSSIBLE \\ \ \\ Sample \ \ Output3: \\NOT\ \ UNIQUE Sample  Output1:ABC Sample  Output2:NOT  POSSIBLE Sample  Output3:NOT  UNIQUE

数据范围
s 的 长 度 N ∈ [ 2 , 2000001 ] 。 s的长度N∈[2,2000001]。 sN[2,2000001]

题解:

① 、 若 N 为 偶 数 , 必 然 无 法 复 原 。 ② 、 先 删 除 一 个 字 符 , 枚 举 删 除 的 位 置 , 再 判 断 中 点 两 侧 的 子 串 是 否 相 同 。 需 要 注 意 的 是 , 若 用 s t r i n g 类 函 数 , 结 果 会 R E , 所 以 只 能 考 虑 哈 希 来 做 。 ①、若N为偶数,必然无法复原。\\②、先删除一个字符,枚举删除的位置,再判断中点两侧的子串是否相同。\\ \qquad需要注意的是,若用string类函数,结果会RE,所以只能考虑哈希来做。 NstringRE

具体落实:

① 、 若 s 长 度 为 偶 数 , 直 接 输 出 。 ② 、 预 处 理 整 个 s 的 哈 希 值 。 ③ 、 枚 举 删 除 的 位 置 , 重 点 在 于 求 删 除 后 , 计 算 中 点 两 侧 的 子 串 的 哈 希 值 s 1 、 s 2 。 设 s 的 长 度 为 n , 则 分 别 分 成 两 种 情 况 :   ( 1 ) 、 删 除 的 位 置 i < = ⌊ n 2 ⌋ , 也 就 是 左 侧 的 子 串 需 要 分 成 两 段 来 计 算 哈 希 值 。 左 侧 的 哈 希 值 = 区 间 [ 1 , i − 1 ] 的 哈 希 值 + 区 间 [ i + 1 , ⌊ n 2 ⌋ + 1 ] 的 哈 希 值 。 抽 象 地 , s 1 = h [ 1 , i − 1 ] + h [ i + 1 , ⌊ n 2 ⌋ + 1 ] 。 还 要 注 意 , h [ 1 , i − 1 ] 需 要 向 高 位 移 动 ⌊ n 2 ⌋ − i + 1 位 , 即 在 i 右 侧 的 字 符 的 数 量 。 ①、若s长度为偶数,直接输出。\\②、预处理整个s的哈希值。\\③、枚举删除的位置,重点在于求删除后,计算中点两侧的子串的哈希值s_1、s_2。\\\qquad设s的长度为n,则分别分成两种情况:\\\ \\\qquad(1)、删除的位置i<=\lfloor\frac{n}{2}\rfloor,也就是左侧的子串需要分成两段来计算哈希值。\\\qquad 左侧的哈希值=区间[1,i-1]的哈希值+区间[i+1,\lfloor\frac{n}{2}\rfloor+1]的哈希值。\\\qquad抽象地,s1=h[1,i-1]+h[i+1,\lfloor\frac{n}{2}\rfloor+1]。\\\qquad还要注意,h[1,i-1]需要向高位移动\lfloor\frac{n}{2}\rfloor-i+1位,即在i右侧的字符的数量。 sss1s2sn (1)i<=2n,=[1,i1]+[i+1,2n+1],s1=h[1,i1]+h[i+1,2n+1]h[1,i1]2ni+1i
在这里插入图片描述
否 则 的 话 , 左 侧 哈 希 值 为 区 间 [ 1 , ⌊ n 2 ⌋ ] 的 哈 希 值 , 即 s 1 = h [ 1 , ⌊ n 2 ⌋ ] 。   ( 2 ) 、 删 除 位 置 i < = ⌊ n 2 ⌋ + 1 , 这 时 右 侧 区 间 的 长 度 > = ⌊ n 2 ⌋ , 故 右 侧 子 串 的 哈 希 值 可 直 接 计 算 。 s 2 = h [ n − ⌊ n 2 ⌋ + 1 , n ] , 这 里 左 端 点 通 过 右 端 点 来 确 定 比 较 容 易 。 否 则 , 右 侧 子 串 的 哈 希 值 需 要 分 成 两 端 计 算 。 左 侧 子 串 哈 希 值 = 区 间 [ ⌊ n 2 ⌋ + 1 , i − 1 ] 的 哈 希 值 + 区 间 [ i + 1 , n ] 的 哈 希 值 。 即 s 2 = h [ ⌊ n 2 ⌋ + 1 , i − 1 ] + [ i + 1 , n ] 。 同 样 的 , h [ ⌊ n 2 ⌋ + 1 , i − 1 ] 需 要 向 高 位 移 动 n − ( i + 1 ) + 1 位 , 即 i 右 侧 的 字 符 的 数 量 。 \qquad否则的话,左侧哈希值为区间[1,\lfloor\frac{n}{2}\rfloor]的哈希值,即s_1=h[1,\lfloor\frac{n}{2}\rfloor]。\\ \ \\ \qquad(2)、删除位置i<=\lfloor\frac{n}{2}\rfloor+1,这时右侧区间的长度>=\lfloor\frac{n}{2}\rfloor,故右侧子串的哈希值可直接计算。\\\qquad s_2=h[n-\lfloor\frac{n}{2}\rfloor+1,n],这里左端点通过右端点来确定比较容易。\\\qquad否则,右侧子串的哈希值需要分成两端计算。\\\qquad左侧子串哈希值=区间[\lfloor\frac{n}{2}\rfloor+1,i-1]的哈希值+区间[i+1,n]的哈希值。\\\qquad即s2=h[\lfloor\frac{n}{2}\rfloor+1,i-1]+[i+1,n]。\\\qquad同样的,h[\lfloor\frac{n}{2}\rfloor+1,i-1]需要向高位移动n-(i+1)+1位,即i右侧的字符的数量。 [1,2n]s1=h[1,2n] (2)i<=2n+1,>=2n,s2=h[n2n+1,n],=[2n+1,i1]+[i+1,n]s2=h[2n+1,i1]+[i+1,n]h[2n+1,i1]n(i+1)+1i
在这里插入图片描述
向 高 位 移 动 i 位 就 是 乘 基 数 b a s e 的 i 次 方 , 即 b a s e i 。 向高位移动i位就是乘基数base的i次方,即base^{i}。 ibaseibasei

④ 、 若 两 侧 哈 希 值 相 等 , 需 要 记 录 第 一 次 哈 希 值 以 及 删 除 的 位 置 i 。 ( 一 开 始 以 为 只 要 符 合 条 件 的 位 置 找 到 2 个 , 就 判 断 方 案 不 唯 一 , 事 实 上 是 不 符 合 题 意 的 , 因 为 删 除 不 同 位 置 的 字 符 , 两 侧 的 哈 希 值 可 能 都 为 同 一 值 。 ) 因 此 需 要 记 录 哈 希 值 , 若 再 次 相 等 时 , 哈 希 值 与 第 一 次 的 哈 希 值 不 同 , 说 明 方 案 不 唯 一 。 ④、若两侧哈希值相等,需要记录第一次哈希值以及删除的位置i。\\\qquad(一开始以为只要符合条件的位置找到2个,就判断方案不唯一,事实上是不符合题意的,\\\qquad因为删除不同位置的字符,两侧的哈希值可能都为同一值。)因此需要记录哈希值,\\\qquad若再次相等时,哈希值与第一次的哈希值不同,说明方案不唯一。 i(2)


代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#define ull unsigned long long
using namespace std;
const int base=131;
const int N=2e6+10;
int n,pos;
ull p[N],h[N],ans;
bool flag;
char s[N];

ull get(int l ,int r)
{
    return h[r]-h[l-1]*p[r-l+1];
}

int main()
{
        scanf("%d",&n);
        scanf("%s",s+1);
        if(n%2==0) {puts("NOT POSSIBLE");return 0;}

        p[0]=1;
        for(int i=1;i<=n;i++) p[i]=p[i-1]*base;

        for(int i=1;i<=n;i++) h[i]=h[i-1]*base+s[i]-'A';

        for(int i=1;i<=n;i++)
        {
            ull s1,s2;
            if(i<=n/2) s1=get(i+1,n/2+1)+h[i-1]*p[n/2-i+1];
            else s1 = h[n/2];
            if(i<=n/2+1) s2=get(n-n/2+1,n);
            else s2=get(n/2+1,i-1)*p[n - i]+get(i+1,n);
            if(s1==s2)
            {
                if(flag && ans != s1)
                {
                    printf("NOT UNIQUE\n");
                    return 0;
                }
                flag=true,ans=s1,pos=i;
            }
        }
        
        if(flag)
        {
            for(int i=1,j=0;j<n/2;i++)
                if(i!=pos)
                    printf("%c",s[i]),j++;
            printf("\n");
        }
        else puts("NOT POSSIBLE");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值