boolkmp(std::string& s, std::string& t){ if (t.length() > s.length())returnfalse; auto next = get_next(t);
for (int i = 0, j = 0; i < (int)s.size() && j < (int)t.size();) { if (j == -1 || s[i] == t[j]) { ++i, ++j; } else j = next[j]; if (j == (int)t.size())returntrue; } returnfalse; }
zfunction
获取字符串 和 (即以 开头的后缀)的最长公共前缀(LCP)的长度,总复杂度 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
std::vector<int> z_function(std::string s){ int n = (int)s.length(); std::vector<int> z(n); for (int i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r && z[i - l] < r - i + 1) { z[i] = z[i - l]; } else { z[i] = std::max(0, r - i + 1); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; } if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } return z; }
最长公共子序列 LCS
求解两个串的最长公共子序列的长度。
小数据解
针对 以内的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
constint N = 1e3 + 10; char a[N], b[N]; int n, m, f[N][N]; voidsolve(){ cin >> n >> m >> a + 1 >> b + 1; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++){ f[i][j] = max(f[i - 1][j], f[i][j - 1]); if (a[i] == b[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1); } cout << f[n][m] << "\n"; } intmain(){ solve(); return0; }
structManachar { std::vector<int> d1, d2; Manachar(std::string s) { int n = s.length(); d1.assign(n, 0); d2.assign(n, 0); for (int i = 0, l = 0, r = -1;i < n;++i) { int k = (i > r) ? 1 : std::min(d1[l + r - i], r - i + 1); while (i + k < n && i - k >= 0 && s[i + k] == s[i - k])k++; d1[i] = k--; if (i + k > r) { r = i + k; l = i - k; } } for (int i = 0, l = 0, r = -1;i < n;++i) { int k = (i > r) ? 0 : std::min(d2[l + r - i + 1], r - i + 1); while (i + k < n && i - k - 1 >= 0 && s[i + k] == s[i - k - 1])k++; d2[i] = k--; if (i + k > r) { r = i + k; l = i - k - 1; } } } boolcheck(int l, int r){ if (r < l)returnfalse; int len = r - l + 1; if (len % 2) { return d1[l + len / 2] * 2 - 1 < len; } else { return d2[l + len / 2] * 2 < len; } } };
structTrie { int ch[N][63], cnt[N], idx = 0; map<char, int> mp; voidinit(){ LL id = 0; for (char c = 'a'; c <= 'z'; c++) mp[c] = ++id; for (char c = 'A'; c <= 'Z'; c++) mp[c] = ++id; for (char c = '0'; c <= '9'; c++) mp[c] = ++id; } voidinsert(string s){ int u = 0; for (int i = 0; i < s.size(); i++) { int v = mp[s[i]]; if (!ch[u][v]) ch[u][v] = ++idx; u = ch[u][v]; cnt[u]++; } } LL query(string s){ int u = 0; for (int i = 0; i < s.size(); i++) { int v = mp[s[i]]; if (!ch[u][v]) return0; u = ch[u][v]; } return cnt[u]; } voidClear(){ for (int i = 0; i <= idx; i++) { cnt[i] = 0; for (int j = 0; j <= 62; j++) { ch[i][j] = 0; } } idx = 0; } } trie;
structTrie { int n, idx; vector<vector<int>> ch; Trie(int n) { this->n = n; idx = 0; ch.resize(30 * (n + 1), vector<int>(2)); } voidinsert(int x){ int u = 0; for (int i = 30; ~i; i--) { int &v = ch[u][x >> i & 1]; if (!v) v = ++idx; u = v; } } intquery(int x){ int u = 0, res = 0; for (int i = 30; ~i; i--) { int v = x >> i & 1; if (ch[u][!v]) { res += (1 << i); u = ch[u][!v]; } else { u = ch[u][v]; } } return res; } };
// Trie+Kmp,多模式串匹配 structACAutomaton { staticconstexprint N = 1e6 + 10; int ch[N][26], fail[N], cntNodes; int cnt[N]; ACAutomaton() { cntNodes = 1; } voidinsert(string s){ int u = 1; for (auto c : s) { int &v = ch[u][c - 'a']; if (!v) v = ++cntNodes; u = v; } cnt[u]++; } voidbuild(){ fill(ch[0], ch[0] + 26, 1); queue<int> q; q.push(1); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = 0; i < 26; i++) { int &v = ch[u][i]; if (!v) v = ch[fail[u]][i]; else { fail[v] = ch[fail[u]][i]; q.push(v); } } } } LL query(string t){ LL ans = 0; int u = 1; for (auto c : t) { u = ch[u][c - 'a']; for (int v = u; v && ~cnt[v]; v = fail[v]) { ans += cnt[v]; cnt[v] = -1; } } return ans; } };
SequenceAutomaton(vector<int> &in, int size) : ver(size + 1) { for (int i = 0; i < in.size(); i++) { ver[in[i]].push_back(i + 1); } } boolcontains(vector<int> &in){ int at = 0; for (auto &i : in) { auto it = lower_bound(ver[i].begin(), ver[i].end(), at + 1); if (it == ver[i].end()) { returnfalse; } at = *it; } returntrue; } };