1. 程式人生 > >【 雜湊和雜湊表】Three Friends

【 雜湊和雜湊表】Three Friends

問題 E: 【 雜湊和雜湊表】Three Friends

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 30  解決: 4
[提交] [狀態] [討論版] [命題人:admin]

題目描述

Three friends like to play the following game. The first friend chooses a string S. Then the second friend constructs a new string T that consists of two copies of the string S. finally, the third friend inserts one letter at the beginning, the end or somewhere inside the string T, thereby creating a string U.
You are given the string U and your task is to reconstruct the original string S.

輸入

The first line of the input contains N(2 ≤ N ≤ 2000001), the length of the final string U. The string U itself is given on the second line. It consists of N uppercase English letters (A, B, C, . . . , Z).

輸出

Your program should print the original string S. However, there are two exceptions:
1.If the final string U could not have been created using the above procedure, you should print NOT POSSIBLE.
2.If the original string S is not unique, you should print NOT UNIQUE.

樣例輸入

7
ABXCABC

樣例輸出

ABC

第一個人選一個串s,第二個人將s複製,得到一個ss串,第三個人在串的任意位置加一個字元得到最終串u

現在給你u,讓你求原始串s,如果有多個原始串s,輸出NOT UNIQUE,如果求不出,輸出NOT POSSIBLE

看樣例,

第一個人選了ABC,第二個人變成ABCABC,第三個人在第一個B後面加個X

字串hash,題目並不難,可我卻讀錯了題,不唯一指的是多個不同的原式串s,而不是多種情況

例如aaa,則應該輸出a,因為雖然有三種方式得到原始串s,但是原始串s是唯一的

 

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef pair<ull,ull> pull;
const int maxn = 2e6+7;
map<pull,bool> M;
const pull p{131LL,13331LL},one{1LL,1LL},zero{0LL,0LL};
pull operator - (pull a,pull b){return make_pair((a.first -  b.first),(a.second - b.second));}
pull operator * (pull a,pull b){return make_pair((a.first *  b.first),(a.second * b.second));}
pull operator + (pull a,pull b){return make_pair((a.first +  b.first),(a.second + b.second));}
pull operator + (pull a,int  b){return make_pair((a.first +  b      ),(a.second + b       ));}
pull Pow(pull a,int n){
    pull ans = one;
    while(n){
        if(n&1)ans = ans*a;
        a = a*a;
        n>>=1;
    }
    return ans;
}
pull Strcut(pull *Len,int l,int r){
    return r<l?zero:Len[r] - Len[l-1]*Pow(p,r-l+1);
}
pull Splice(pull a,pull b,int n){
    return (n < 0)?a:a*Pow(p,n)+b;
}
pull crups(pull *Len,int l,int r,int k){
	if(k<l || k>r)
		return Strcut(Len,l,r);
	return Splice(Strcut(Len,l,k-1),Strcut(Len,k+1,r),r-(k+1) +1);
}
char a[maxn];
pull Len[maxn];
int main(){
    int n;
    scanf("%d",&n);
    scanf("%s",a+1);
    for(int i=1;i<=n;i++)
        Len[i] = Len[i-1]*p + a[i];
    int ansk = -1,flag = 0;
    for(int k=1;k<=n;k++){
       pull x = k< n/2+1?crups(Len,1,n/2+1,k):crups(Len,1,n/2,k);
       pull y = k<=n/2+1?crups(Len,n/2+2,n,k):crups(Len,n/2+1,n,k);
       if(x == y){
            if(ansk != -1){
                if(!M.count(x))
                    flag = 1;
            }
            ansk = k;
            M[x] = 1;
       }
    }
    if(ansk == -1)
        printf("NOT POSSIBLE\n");
    else if(flag)
        printf("NOT UNIQUE\n");
    else{
        if(ansk<=n/2)for(int i=n/2+2;i<=n  ;i++)printf("%c",a[i]);
        else         for(int i=1    ;i<=n/2;i++)printf("%c",a[i]);
        printf("\n");
    }
    return 0;
}