KMP

xiaoxiao2021-02-27  525

KMP算法

KMP_Pre

/* * next[]的含义,x[i - next[i]...i - 1] = x[0...next[i] - 1] * next[i]为满足x[i - z...i - 1] = x[0...z - 1]的最大z值(就是x的自身匹配) */ void KMP_Pre(char x[], int m, int next[]) { int i, j; j = next[0] = -1; i = 0; while (i < m) { while (-1 != j && x[i] != x[j]) { j = next[j]; } next[++i] = ++j; } return ; }

preKMP

/* * kmpNext[]的意思:next'[i] = next[next[...[next[i]]]] * (直到next'[i] < 0或者x[next'[i]] != x[i]) * 这样的预处理可以快一些 */ void preKMP(char x[], int m, int kmpNext[]) { int i, j; j = kmpNext[0] = -1; i = 0; while (i < m) { while (-1 != j && x[i] != x[j]) { j = kmpNext[j]; } if (x[++i] == x[++j]) { kmpNext[i] = kmpNext[j]; } else { kmpNext[i] = j; } } return ; }

KMP_Count

/* * 此函数与上述两个函数中的任意一个搭配使用(即调用上述两个函数中的任意一个) * 返回x在y中出现的次数,可以重叠 */ int next[10010]; int KMP_Count(char x[], int m, char y[], int n) { // x是模式串,y是主串 int i, j; int ans = 0; // preKMP(x, m, next); KMP_Pre(x, m, next); i = j = 0; while (i < n) { while (-1 != j && y[i] != x[j]) { j = next[j]; } i++, j++; if (j >= m) { ans++; j = next[j]; } } return ans; }

扩展KMP

* * 扩展KMP * next[i]:x[i...m-1]的最长公共前缀 * extend[i]:y[i...n-1]与x[0...m-1]的最长公共前缀 */ void preEKMP(char x[], int m, int next[]) { next[0] = m; int j = 0; while (j + 1 < m && x[j] == x[j + 1]) { j++; } next[1] = j; int k = 1; for (int i = 2; i < m; i++) { int p = next[k] + k - 1; int L = next[i - k]; if (i + L < p + 1) { next[i] = L; } else { j = std::max(0, p - i + 1); while (i + j < m && x[i + j] == x[j]) { j++; } next[i] = j; k = i; } } return ; } void EKMP(char x[], int m, char y[], int n, int next[], int extend[]) { preEKMP(x, m, next); int j = 0; while (j < n && j < m && x[j] == y[j]) { j++; } extend[0] = j; int k = 0; for (int i = 1; i < n; i++) { int p = extend[k] + k - 1; int L = next[i - k]; if (i + L < p + 1) { extend[i] = L; } else { j = std::max(0, p - i + 1); while (i + j < n && j < m && y[i + j] == x[j]) { j++; } extend[i] = j; k = i; } } return ; }

转载请注明原文地址: https://www.6miu.com/read-7289.html

最新回复(0)