知识点:哈希算法

题意:

给定字符串S,对字符串S+S,插入一个数,得到T,现在给你T,让你求出可能的S字符串,根据情况,答案分为,输出唯一的S,或输出“NOT POSSIBLE”或“NOT UNIQUE”。

思路:

比较暴力的一个题,但是拿到的第一瞬间没有思路,是因为对于hash的理解还不到位,以及这道题调了非常久的时间。但是这是非常不应该的,错误在于。if(n&1==0)这个判断没有打括号(正解:if((n&1)==0) ),切记啊,记不得优先级就得狂打括号!空耗好几个小时。暴力枚举x的位置,然后再根据x的位置和字符串中位的关系,构建前一半的hash和后一半的hash,判断是否相等。注意,根据题意,多种方案得到的同一个S,也是唯一的解。

题解代码:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
#include<map>
#define rep(i,l,n) for(int i=(l);i<=(n);++i)
#define ll long long
#define ull unsigned long long
#define N 2000010
using namespace std;
ull h[N],p[N]={1},l,r,mid,base=707;
map <ull,int> mp;
char s[N];
int ans[100],cnt,len,n;
void shash()
{
    rep(i,1,n)
    {
        h[i]=h[i-1]*base+(ull)s[i];
        p[i]=p[i-1]*base;
    }
    return ;
}
void pd(ull l,ull r,int i)
{
    if(l==r&&mp[l]==0)
    {
            ans[++cnt]=i;
            mp[l]=1;
    }
    return;
}
int main()
{
    scanf("%d",&n);
    if((n&1)==0){puts("NOT POSSIBLE");return 0;}
    scanf("%s",s+1);
    len=n/2;
    shash();
    rep(i,1,n)
    {
        if(i<=len)
        {
            l=h[i-1],mid=h[len+1]-h[i]*p[len+1-i],r=h[n]-h[n-len]*p[len];
            l=l*p[len+1-i]+mid;
            pd(l,r,i);
        }
        else if(i==len+1)
        {
            l=h[i-1],r=h[n]-h[i]*p[len];
            pd(l,r,i);
        }
        else 
        {
            l=h[len],r=h[n]-h[i]*p[n-i],mid=h[i-1]-h[len]*p[i-len-1];
            r=mid*p[n-i]+r;
            pd(l,r,i);
        }
        if(cnt>1)break;
    }
    if(cnt==1)
    {
        int j=1;
        while(j<=len)
        {
            if(j==ans[cnt])++j,len++;
            printf("%c",s[j]);
            ++j;
        }
    }
    else if(cnt==0)
    {
        puts("NOT POSSIBLE");
    }
    else
    {
        puts("NOT UNIQUE");
    }
  //  system("pause");
    return 0;
}
 posted on 2022-09-21 00:29  8号选手  阅读(31)  评论(0)    收藏  举报