CodeVS1404 字串匹配(擴充套件kmp)

2021-07-15 22:32:33 字數 1734 閱讀 4747

題目描述 description

給你兩個串a,b,可以得到從a的任意位開始的子串和b匹配的長度。

給定k個詢問,對於每個詢問給定乙個x,求出匹配長度恰為x的位置有多少個。

n,m,k<=200000

輸入描述 input description

第一行三個數 n,m,k,表示a的長度、b的長度和詢問數。

第二行為串a。

第三行為串b。

接下來k行,每行1個數x。

輸出描述 output description

對於每個詢問輸出乙個數。

樣例輸入 sample input

6 2 2

aabcdeab0

2 樣例輸出 sample output 4

1 資料範圍及提示 data size & hint

各個測試點1s

假如有匹配串a長度為n,模式串b長度為m,那麼擴充套件kmp演算法可以在o(n+m)的時間內算出對於a的每乙個位置,與b的最長匹配長度是多少(即與b串字首重合的最長長度),演算法如下:

設next[i]表示b串的i位置開始的字串與b串的字首的最長重合長度(注意這裡與kmp中的next是不一樣的)。明顯地,next[1]=m(我的字串的下標習慣從1開始),next[2]也可以用乙個簡單的for迴圈求出,pos初始化為2;當i∈[3,m]時,我首先認為關於1~i-1的資訊已全部求出,我們記錄乙個pos,它的意義是當前已計算出的next陣列中,j+next[j]-1能達到的最右端所對應的i,這個不太好理解,可以參考manacher演算法的思想戳這(其實manacher和擴充套件kmp是很像的),令rp=pos+next[pos]-1

(1)當i+next[i-pos+1]

(2)當i+next[i-pos+1]>=rp時,rp後的元素,即b[rp+j],可能會和b[rp-i+1+j]相等,這時進行暴力擴充套件,如果擴充套件發生,則更新pos為i,next[i]直接在擴充套件中求出。

注意:有時rp可能小於i,這時可以加一特判,直接進行暴力求

令ans[i]表示a串中以a[i]為開頭的字尾和b串的最長匹配長度,設pos表示a串中對於所有的i,i+ans[i]-1能達到的最遠位置對應的i,rp就是pos+ans[pos]-1,next[1]暴力求出,pos初始化為1;當i∈[2,n]時:

(1)若i+next[i-pos+1]-1

(2)若i+next[i-pos+1]-1>=rp,則進行暴力擴充套件,同時更新pos,ans在擴充套件時求出

注意:如果rp

//codevs1404 字串匹配 擴充套件kmp

#include #include #include #define maxlen 200010

using namespace std;

char a[maxlen], b[maxlen];

int next[maxlen], n, m, k, cnt[maxlen], ans[maxlen], tong[maxlen];

void init()

else

if(i+next[i]-1>p)a=i;

} else next[i]=next[i-a+1]; }}

void exkmp()

else

}else ans[i]=next[i-pos+1];

if(i+ans[i]-1>rp)pos=i;

tong[ans[i]]++; }}

int main()

return 0;

}

CODEVS T 1404 字串匹配

時間限制 1 s 空間限制 128000 kb 題目等級 大師 master 題解檢視執行結果 給你兩個串a,b,可以得到從a的任意位開始的子串和b匹配的長度。給定k個詢問,對於每個詢問給定乙個x,求出匹配長度恰為x的位置有多少個。n,m,k 200000 輸入描述 input descriptio...

201409 3 字串匹配

試題編號 201409 3 試題名稱 字串匹配 時間限制 1.0s 記憶體限制 256.0mb 問題描述 問題描述 給出乙個字串和多行文字,在這些文字中找到字串出現的那些行。你的程式還需支援大小寫敏感選項 當選項開啟時,表示同乙個字母的大寫和小寫看作不同的字元 當選項關閉時,表示同乙個字母的大寫和小...

20140903 字串匹配

問題描述 試題編號 201409 3 試題名稱 字串匹配 時間限制 1.0s 記憶體限制 256.0mb 問題描述 問題描述 給出乙個字串和多行文字,在這些文字中找到字串出現的那些行。你的程式還需支援大小寫敏感選項 當選項開啟時,表示同乙個字母的大寫和小寫看作不同的字元 當選項關閉時,表示同乙個字母...