「BalticOI 2014 Day 1」三個朋友【字符串哈希】

題目描述
本題譯自 BalticOI 2014 Day1 T2「Three Friends」

給定一個字符串 ,先將字符串 複製一次(變成雙倍快樂),得到字符串 ,然後在 中插入一個字符,得到字符串 。

給出字符串 ,重新構造出字符串 。

所有字符串只包含大寫英文字母。

輸入格式
第一行一個整數 ,表示字符串 的長度。

第二行一個長度爲 的字符串,表示字符串 。

輸出格式
一行一個字符串,表示字符串 。

特別地:

如果字符串無法按照上述方法構造出來,輸出 NOT POSSIBLE;
如果字符串 不唯一,輸出 NOT UNIQUE。
樣例
樣例輸入 1
7
ABXCABC
樣例輸出 1
ABC
樣例輸入 2
6
ABCDEF
樣例輸出 2
NOT POSSIBLE
樣例輸入 3
9
ABABABABA
樣例輸出 3
NOT UNIQUE

分析:顯然字符串哈希,這題主要是想考對哈希的理解。
字符串刪了一個字符,哈希值會怎麼改變?
如S=“ABCD”,S’=“ABD”
S的哈希值=1×b3+2×b2+3×b1+4
S’的哈希值=1×b2+2×b1+4
就是C後面的哈希值不變,前面的哈希值會根據後面的長度進行改變,可以多造幾個例子加深理解
那麼這題就A了。
但是判重很麻煩,我省力直接用的mapA了,但是時間多了個log。後面我覺得可以在最後統計一下答案,別忘了字符串可以直接比較的,這樣時間更快。
但我太弱了還懶qaq

#include<cstring> 
#include<bits/stdc++.h>
#define ULL unsigned long long 
using namespace std;
ULL Hash,hash[2000010];
ULL b=11;
ULL power[2000010];
char A[2000010];
int sum,ans;
map<int,bool> flag;
int main()
{
	int l;
	power[0]=1;
	for(int i=1;i<=2e6;i++)
	power[i]=power[i-1]*b;
	scanf("%d",&l);
	scanf("%s",A);
	if(l%2==0)
	{
		printf("NOT POSSIBLE");
		return 0;
	}
	{
		for(int i=0;i<l;i++)
		{
			hash[i+1]=hash[i]*b+(ULL)(A[i]-'A'+1);
		}
		for(int i=1;i<=(l>>1);i++)
		{
			if(hash[(l>>1)+1]-hash[i]*power[(l>>1)+1-i]+hash[i-1]*power[(l>>1)-i+1]==hash[l]-hash[(l>>1)+1]*power[l>>1]&&flag[hash[l]-hash[(l>>1)+1]*power[l>>1]]==0)
			sum++,ans=i,flag[hash[l]-hash[(l>>1)+1]*power[l>>1]]=1;
		}
		if(hash[l>>1]==hash[l]-hash[(l>>1)+1]*power[l>>1]&&flag[hash[l>>1]]==0)
		sum++,ans=(l>>1)+1,flag[hash[l>>1]]=1;
		for(int i=(l>>1)+2;i<=l;i++)
		{
			if(hash[l]-hash[i]*power[l-i]+(hash[i-1]-hash[(l>>1)]*power[i-1-(l>>1)])*power[l-i]==hash[l>>1]&&flag[hash[l>>1]]==0)
			sum++,ans=i,flag[hash[l>>1]]=1;
		}
		if(sum==0) printf("NOT POSSIBLE");
		else if(sum>=2) printf("NOT UNIQUE");
		else
		{
			if(ans<=(l>>1)+1)
			for(int i=(l>>1)+2;i<=l;i++)
			printf("%c",A[i-1]);
			else for(int i=0;i<(l>>1);i++)
			printf("%c",A[i]);
		}
	}
	return 0;
}

前面有段時間沒學OI了,因爲要出國了,但是發現好無聊啊文化課又學不懂英語菜死了就繼續學了,還是OI好玩。以後繼續寫 qaq
謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章