GDOI2016模擬8 18解密

2021-07-04 16:35:03 字數 1751 閱讀 2317

題目

mirko要解一段加密文,但他只知道某乙個句子是原文的一部分。你的任務是要在密文中找到第乙個對應這個句子的地方。

文段是通過用某個單詞(可能和原文一樣的單詞)替換原始文段每乙個單詞來加密的。如果某些單詞在原文出現一次以上,就會使用相同的替換單詞來替換。沒有兩個不同的單詞使用相同的替換單詞。

單詞是通過空格隔開的小寫字母序列。句子是連續單詞的序列。

這題我們可以通過最小表示法+hash來做。

首先對於模板串,我們記錄下陣列a[i]表示成與第i個字串相同的下乙個串在哪個位置,然後將其視作乙個p進製數(p是乙個質數),然後mod p1(p1是另乙個大質數)將其hash起來,得到新的表示形式s(這個可以證明和將相同的字串表示成相同的編號並使字典序最小的最小表示法是等價的,因為我們並不關心具體的字串,只關心相同字串之間的關係(乙個比較尋常的聯絡就是它們之間的距離和出現的位置,將位置視作數字,將距離視作該數字的數值,得到乙個k進製數即可表示(當然,比較多變化的通常是數值:有時候是距離,有時候是編號)))

用相同的方法我們可以處理匹配串的前len個字串(len為匹配串的字串個數),注意,若相同的字串超出len(即i和j為最近的相同字串,i在len以內,j在len以外,則將i那一位視作0)則不計算那一位(把距離看做0),由於多出來的在模板串是沒出現的,得到匹配串的新型式f,將f與s比較,如相同則為ans。

接著我們可以試著移動指標來匹配匹配串中後續len個字元,這裡我們可以將f看做p1進製數,當前面出去乙個,(若之前加入過,有的距離會超過len,所以會有沒有加入過的)將其減去,若出現l≤i≤r,且最近的與i相同字串位於r(也就是之前並沒計入,後來要計入了),就找到i對應的數字加上就行。

每次處理完就與s比較一下,ans就是第一次s與f相同的位置

對於找相鄰相同的字串,掃一遍,可以用雙hash(資料有卡),也可以轉成26進製(不能直接用string否則爆空間)後取mod用map來弄。

貼**(由於擔心出錯機率大,我將距離乘上乙個權值再轉成k進製,這裡可以不乘,若擔心因此看不懂程,可以將help和mod1去掉)

#include

#include

#include

#define mod 1000000007

#define mod3 10007

#define mod1 9999991

#define mod2 1000007

#include

#include

using

namespace

std;

#define n 1000001

maplong,int>f;

int n,len,len1,ans;

long

long s;

long

long a[n],b[n],help[n],help1[n];

char c[n];

long

long get()

void pre()

void init()

len1=y;

y=0;

scanf(" %s",&c);

f.clear();

while (c[0]!='$')

len=y;

f.clear();

}void work()

if (ss==s)

l=0;

for (int i=len+1;i<=len1;i++)

}}void write()

int main()

GDOI2016模擬8 8旋轉

alice和bob發明了乙個新的旋轉遊戲。首先,bob給定n個數組成的序列,並把該序列平均分配成若干個塊,每塊正好包含k個數 k能整除n 第一塊由第1到第k個數構成,第二塊由第k 1個數到第2k個數構成,以此類推。接著,bob要求alice對這個序列進行一系列操作,操作有以下兩種 1.把每塊裡面的數...

GDOI2016模擬8 13總結

這次考差了。但事後想了一下,感覺收穫好大。匯報做題情況 當然,裡面不包含收穫 第一題 我的暴力爆零了,原因又是爆int 做題過程中我想到了與眾不同的演算法,一般人會化簡不等式變成斜率優化做,但由於我對斜率優化不大敏感,而且一般斜率優化的題目都是用凸包 叉積來做,這題我也同樣想著用凸包做,但打完發現有...

GDOI2016模擬8 16幫派

農場裡的生活很艱苦,而且當生活很艱苦,你必須堅強起來。奶牛們形成了編號為1到m的幫派。這些幫派一開始和睦相處了一段時間,但是現在失控了!奶牛們在競爭一片大草地的控制權。奶牛之間的衝突發生在連續的若干分鐘內。每一分鐘有乙隻奶牛走進草地。如果此時草地上沒有奶牛,那麼這只新進去的奶牛所在的幫派就能占領這片...