for (int i = 1; i < n; i++) { int j = bd[i-1]; while (j && s[i] != s[j]) j = bd[j-1]; if (s[i] == s[j]) j++; bd[i] = j; }
字符串下标从 \(0\) 开始。
exKMP(Z函数)
定义:
\(z_i\):字符串 \(s\) 与 \(s\) 以 \(i\) 为起始的后缀的最长公共前缀。
代码:
1 2 3 4 5 6 7 8 9 10 11
voidgetZ(const string& s, int z[]){ int n = s.size(), l = 0, r = -1; for (int i = 1; i < n; i++) { int k = (i > r) ? 0 : min(z[i-l], r-i+1); while (i+k < n && s[i+k] == s[k]) k++; z[i] = k; if (i+k-1 > r) l = i, r = i+k-1; } z[0] = n; }
int n = s.size(); int len = 0, nl = 0, nr = 0; for (int i = 0, l = 0, r = -1; i < n; i++) { int k = (i>r) ? 1 : min(d1[l+r-i], r-i+1); while (0<=i-k && i+k<n && s[i-k]==s[i+k]) k++; d1[i] = k--; if (i+k>r) l = i-k, r = i+k; if (r-l+1 > len) len = r-l+1, nl = l, nr = r; } for (int i = 0, l = 0, r = -1; i < n; i++) { int k = (i>r) ? 0 : min(d2[l+r-i+1], r-i+1); while (0<=i-k-1 && i+k<n && s[i-k-1]==s[i+k])k++; d2[i] = k--; if (i+k>r) l = i-k-1, r = i+k; if (r-l+1 > len) len = r-l+1, nl = l, nr = r; }