[bzoj3916] friends

Description

有三个好朋友喜欢在一起玩游戏,A君写下一个字符串S,B君将其复制一遍得到T,C君在T的任意位置(包括首尾)插入一个字符得到U.现在你得到了U,请你找出S.

Input

第一行一个数N,表示U的长度.

第二行一个字符串U,保证U由大写字母组成

Output

输出一行,若S不存在,输出"NOT POSSIBLE".若S不唯一,输出"NOT UNIQUE".否则输出S.

Sample Input1

7
ABXCABC

Sample Output1

ABC

Sample Input2

6
ABCDEF

Sample Output2

NOT POSSIBLE

Sample Input3

9
ABABABABA

Sample Output3

NOT UNIQUE

Hint

对于100%的数据 2<=N<=2000001

题解

这题很显然是一道字符串\(Hash\),但是有一些坑点

由于我将若S不唯一看成了若插入的位置不唯一,创造了我的首\(WA\)

接着,我却将每次可以的\(S\)记录下来,导致时间代价太大,造成了我的首\(TLE\),\(TLE\)代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;

typedef unsigned long long ull;
const int L=2000005,E=100007;
char s[L],Out[L];
int l,Ans;
ull power[L],h[L];

void PutIn(int id)//超时的关键
{
    if(id<=l/2)
    {
        for(int i=1;i<=l/2;++i) Out[i]=s[i+l/2+1];
        return;
    }
    for(int i=1;i<=l/2;++i) Out[i]=s[i];
}

int Check(int id)//超时的关键
{
    if(id<=l/2)
    {
        for(int i=1;i<=l/2;++i)
            if(Out[i]!=s[i+l/2+1]) return 1;
        return 0;
    }
    for(int i=1;i<=l/2;++i)
        if(Out[i]!=s[i]) return 1;
    return 0;
}

int main()
{
    scanf("%d\n%s",&l,s+1);
    if(l%2==0) {puts("NOT POSSIBLE");goto end;}
    power[0]=1;
    for(int i=1;i<=l;++i) power[i]=power[i-1]*E;
    for(int i=1;i<=l;++i) h[i]=h[i-1]*E+s[i];
    for(int i=1;i<=l;++i)
    {
        if(i<=l/2)
        {
            if((h[l/2+1]-h[i]*power[l/2+1-i]+h[i-1]*power[l/2+1-i])
            ==(h[l]-h[l/2+1]*power[l/2]))
                if(!Ans) {Ans=i;PutIn(i);}
                else if(Check(i))
                        {puts("NOT UNIQUE");goto end;}
        }
        else
        {
            if(h[l/2]
            ==(h[l]-h[i]*power[l-i]+h[i-1]*power[l-i]-h[l/2]*power[l-l/2-1]))
                if(!Ans) {Ans=i;PutIn(i);}
                else if(Check(i))
                        {puts("NOT UNIQUE");goto end;}
        }
    }
    if(!Ans) puts("NOT POSSIBLE");
    else
    {
        for(int i=1;i<=l/2;++i) printf("%c",Out[i]);
        putchar('\n');
    }
    end:
    return 0;
}

注意到上面代码中造成\(TLE\)的罪魁祸首,如果我们能够\(O(1)\)来比较的话那么问题不就迎刃而解了吗

字符串\(Hash\)的作用是什么?

将字符转化成数,从而方便的计算与比较大小,(大雾

\(My~Code\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;

typedef unsigned long long ull;
const int L=2000005,E=100007;
char s[L];
int l,Ans;
ull power[L],h[L],hAns;

int main()
{
    scanf("%d\n%s",&l,s+1);
    if(l%2==0) {puts("NOT POSSIBLE");goto end;}
    power[0]=1;
    for(int i=1;i<=l;++i) power[i]=power[i-1]*E;
    for(int i=1;i<=l;++i) h[i]=h[i-1]*E+s[i];
    for(int i=1;i<=l;++i)
    {
        if(i<=l/2)
        {
            if((h[l/2+1]-h[i]*power[l/2+1-i]+h[i-1]*power[l/2+1-i])
            ==(h[l]-h[l/2+1]*power[l/2]))//此处的过程需要用草稿纸或大脑子
                if(!Ans) Ans=i,hAns=h[l]-h[l/2+1]*power[l/2];
                else if(h[l]-h[l/2+1]*power[l/2]!=hAns)
                    {puts("NOT UNIQUE");goto end;}
        }
        else
        {
            if(h[l/2]
            ==(h[l]-h[i]*power[l-i]+h[i-1]*power[l-i]-h[l/2]*power[l-l/2-1]))
                if(!Ans) Ans=i,hAns=h[l/2];
                else if(h[l/2]!=hAns)
                    {puts("NOT UNIQUE");goto end;}
        }
    }
    if(!Ans) puts("NOT POSSIBLE");
    else
    {
        if(Ans<=l/2)
        {
            for(int i=l/2+2;i<=l;++i) printf("%c",s[i]);
            putchar('\n');
        }
        else
        {
            for(int i=1;i<=l/2;++i) printf("%c",s[i]);
            putchar('\n');
        }
    }
    end:
    return 0;
}
上一篇:bzoj 4811 由乃的OJ


下一篇:new_bzoj(Matrix)