kmp與ac自動機

2021-08-29 09:59:09 字數 1402 閱讀 9502

xj比賽做到一道字串題,結果發現想打個字串匹配都只會n^2了,又一次忘記了kmp(想必是當初學這玩意心理陰影面積太大了。。),這裡再梳理一遍kmp和ac自動機(以便下次再忘了有地方看...)。

kmp:

用於處理對於字串s,想知道它在另外某個串哪些位置出現的問題,先做預處理得到乙個失配陣列,這個陣列第i位表示s的前i位字尾與字首相同的最大長度。這個東西可以o(n)求。(當然這裡注意不能整個字尾與字首不能是當前整個串,不然失配你就在原地跳,re起飛)

之後匹配,當匹配到s的第i位發現失配(或者完全匹配了)後,下乙個有可能匹配到當前末尾的位數一定是當前這一位字尾與字首相同的最大長度(手模一下即可),然後就搞定了。

複雜度分析:**貼吧

這個可以用勢能分析法來分析:

關於匹配指標的位置 cur

操作a:匹配時,cur++;

操作b:失配時,cur = next[cur ]; (根據不同實現有所出入)

這個 next[cur] <= cur - 1 是成立的。

根據勢能分析(cur >= 0 恆成立),我們可以證明,操作a的執行次數一定比操作b要多,兩個操作都是o(1)。

而操作a的執行次數是很容易分析最壞上界是 o(n)

那麼 o(n) = t(a) >= t(b)

因此匹配時的時間複雜度 t(a + b) = o(n)

嗯。。很有道理(假裝懂了)

**:

#includeusing namespace std;

const int n=1000010;

int n1,n2,nxt[n];char s1[n],s2[n];

void cal_fail()

}void pp()

}}int main()

ac自動機:當初因為不會kmp所以這玩意也只會背**,懂了kmp就好理解了。它可以說是kmp進化版,kmp用於求乙個串在其他多個串哪些位置出現,ac自動機則可求多個串在其他多個串哪些位置出現。建法:先建一棵trie樹,然後類似kmp的失配陣列那樣求出每個節點失配指標,就是字典樹里能和當前這個位置的字尾匹配最長的字首(和kmp類似,當然也不能是它本身),求法就是對於節點x,沿著父親的失配指標跳,直到跳到某個節點,它有和x節點代表字元相同的字元的孩子(或者是一直跳到根也沒有)。匹配也就類似kmp模擬一下了。

**:#includeusing namespace std;

char str[160][80],s[1000010];

struct ahonode[12010];int size,cnt[160];

queueq;

void init()

void insert(char *s,int id)

{int n=strlen(s),pos=0,nw;

for(int i=0;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...

KMP 和 AC 自動機(坑)

xyynb kmp這裡,字串從1開始計數!眾所周知,kmp是一種單串匹配演算法,把樸素演算法的o s t 優化到了o s t 如上圖,在進行樸素演算法時,如果我們已經進行了一些匹配成功,實際上我們就知道了原串的一些資訊,理論上就可以使用這個資訊來加速匹配,跳過一些絕對不可能匹配成功的情況。所以,該怎...

AC自動機 建立nlogn個AC自動機

string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...