KMP,擴充套件KMP,AC自動機總結 模板

2022-06-20 20:24:11 字數 3026 閱讀 3075

為了方便統一,本文中下標均從0開始

kmp

p3375 【模板】kmp字串匹配

對於兩個字串s1,s2(s1>s2),求s2在s1中的出現位置

例如s1=ababa,s2=aba

在這個樣例中答案就是0 2

首先考慮暴力做法,對於s1的每乙個字元,我們都一該字元開始往後與s2對比.時間複雜度為\(o(n^2)\)

很明顯這並不是我們想要的,所以考慮優化,仔細觀察一下,其實我們不用每個字元都去列舉一遍

如圖

我們假設圖中綠色區域的字串相等,那麼當第i個字元匹配完時,對於第i+1個字元,我們不需要去列舉所有字元,因為我們可以知道,

圖中綠色區域時已經匹配好了的,所以我們就只需要從綠色區域以後開始匹配就行了.

那麼我們就可以設乙個next陣列,表示以第i個字元終點,相同的字首和字尾的最大長度為多少

如上面的aba

那麼next[0]=1,next[1]=1,next[2]=1

注意不能包括自己本身,因為這樣的話存的東西就沒有了意義,一直都是它本身的長度

那麼在匹配的時候對於第i個字元,如果相等,那麼已經匹配好的長度就加1,如果不等,就開始往回跳

我們每次就往會跳,知道目前匹配的字元與第i個字元相等,這就是匹配的過程,對於求next的過程,其實也差不多,可以看成兩個s2在做匹配

code

#include#includeusing namespace std;

const int n = 1e6 + 5;

string p, s;

int net[n], ans[n], cnt;

int main()

for (int i = 0, j = 0; i < m; i++)

}for (int i = 0; i < n; i++)

cout << net[i] << " ";

return 0;

}

擴充套件kmpp5410 【模板】擴充套件 kmp(z 函式)

之所以叫擴充套件kmp,肯定時因為這個東西要高階一點.s1,s2同上

擴充套件kmp求的東西與kmp中的next有點相似,它求的時以第i個字元為起點的字首與s2的最大字首長度

那麼這個東西要怎麼求?我們先引入乙個z陣列,它表示s2中以第i個字元開頭的字尾與前最的最長公共長度

例如對於s1=aaaabaa,s2=aaaaa

那麼z[0]=5,z[1]=4,z[2]=3,z[3]=2,z[4]=1

考慮暴力做法,對於每乙個字元,同樣是往後遍歷一邊,複雜度為\(o(n^2)\)

那麼如何用這個z陣列來優化這個演算法?

我們假設字串[l,r]是我們之前已經求出的r最大的字首那麼對於s2, 下標就為[0,r-l],那麼這個時候就要分兩種情況討論了,若i>r,

那麼說明我們無法利用前面已知的資訊,只能暴力匹配,若i<=r,那麼我們就可以知道以第i個字元為起點的字首的初始長度應為min(r-i+1,z[i-l]).

如果說z[i-l]是大於r-i+1的,那麼對於r之後的字元,我們任需暴力匹配,但總時間複雜度任為o(n).這點可以證明,在這裡不過多解釋

對於z陣列,求法同kmp的next陣列,將s2與s2自身匹配.

#include#include#includeusing namespace std;

const int n = 2e7 + 5;

typedef long long ll;

char a[n], b[n];

int ex[n], z[n], l1, l2;

void zbox()

}void exkmp()

}int main()

ac自動機kmp保證乙個字串時為線性,那麼對於多個字串,就需要ac自動機了,注意它和自動ac機的區別,它並不能自動ac題目,雖然我以前一直以為它時這個意思.

p3808 【模板】ac自動機(簡單版)

對於乙個字串,以及一堆長度小於它的模式串,求這個字串出現了多少個模式串.

例母串為ababa,模式串為a ab aba bc

那麼答案為3

ac自動機是kmp與trie樹的結合

如樣例,首先建trie樹

其中有綠色標記的代表單詞結尾

其思想其實和kmp差不多,只是改成了在樹上跳而已

**

for (int i = 0, j = 0; str[i]; i++)

}

這裡可以有個優化,就是在建trie圖的時候,直接記錄到可以跳的位置,那麼就可以省掉一層迴圈

#include#include#includeusing namespace std;

const int n = 1e6 + 5;

int tr[n][26], net[n], cnt[n], idx, q[n], front, tail = -1;

char str[n];

void insert()

cnt[p]++;

}void build()}}

}int main()

build();

scanf("%s", &str);

for (int i = 0, j = 0; str[i]; i++)

}printf("%d", ans);

return 0;

}

ac自動機的拓撲優化這裡就不寫

字典樹 kmp ac自動機

講乙個簡單的例子 ababcbababacba 裡面是否包含 bababac 根據我記得最裸的寫法是 o nm 的bf演算法 就是逐個匹配,但是時間非常的浪費。所以有了這kmp。kmp 是針對 模式串 進行預處理過 來達到速度提公升。a bab c bababacba bab a bac 此時我們匹...

kmp與ac自動機

xj比賽做到一道字串題,結果發現想打個字串匹配都只會n 2了,又一次忘記了kmp 想必是當初學這玩意心理陰影面積太大了。這裡再梳理一遍kmp和ac自動機 以便下次再忘了有地方看.kmp 用於處理對於字串s,想知道它在另外某個串哪些位置出現的問題,先做預處理得到乙個失配陣列,這個陣列第i位表示s的前i...

AC自動機(KMP 字典樹)

ac自動機 kmp 字典樹 題目 輸入n個串,判斷有多少個搜尋串的子串 in out 1 47a ababc abcd abcde abcdef abcdefg abcd includeusing namespace std char str 1000000 100 struct node root...