在 ACM 国际大学生程序设计竞赛中,算法的高效实现是取得好成绩的关键。本文将详细介绍竞赛中常用的几类算法模板,包括字符串处理算法、图论算法、动态规划算法以及常用数据结构的实现,帮助参赛者在赛场上快速应用,提升解题效率。
字符串处理算法
字符串处理在 ACM 竞赛中出现频率极高,涉及模式匹配、字符串哈希、前缀后缀等多种操作。以下是几种核心算法的 C++ 实现。
KMP 算法
KMP 算法是解决字符串模式匹配问题的高效算法,其核心在于利用前缀函数(部分匹配表)避免不必要的字符比较。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> computeLPS(string pattern) {
int m = pattern.size();
vector<int> lps(m, 0);
int len = 0; // 长度为len的最长前缀也是后缀
for (int i = 1; i < m; ) {
if (pattern[i] == pattern[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1]; // 回溯
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
vector<int> kmpSearch(string text, string pattern) {
vector<int> result;
int n = text.size();
int m = pattern.size();
if (m == 0) return result;
vector<int> lps = computeLPS(pattern);
int i = 0; // text的索引
int j = 0; // pattern的索引
while (i < n) {
if (pattern[j] == text[i]) {
i++;
j++;
}
if (j == m) {
result.push_back(i - j); // 记录匹配起始位置
j = lps[j - 1];
} else if (i < n && pattern[j] != text[i]) {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return result;
}
int main() {
string text = "ABABDABACDABABCABAB";
string pattern = "ABABCABAB";
vector<int> matches = kmpSearch(text, pattern);
for (int pos : matches) {
cout << "Pattern found at position " << pos << endl;
}
return 0;
}
在上述代码中,computeLPS 函数用于计算模式串的前缀函数数组,kmpSearch 函数则利用该数组进行高效的模式匹配。KMP 算法的时间复杂度为 O (n + m),其中 n 是文本串长度,m 是模式串长度,大大优于朴素匹配算法的 O (n*m)。
字符串哈希
字符串哈希通过将字符串映射为一个整数,实现快速的字符串比较和查询。常用的有单哈希和双哈希(降低冲突概率)。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const int BASE = 911382629;
const int MOD = 1e18 + 3;
// 预处理幂次
vector<ll> powBase;
void precomputePower(int maxLen) {
powBase.resize(maxLen + 1);
powBase[0] = 1;
for (int i = 1; i <= maxLen; i++) {
powBase[i] = (powBase[i - 1] * BASE) % MOD;
}
}
// 计算字符串的哈希值
ll computeHash(const string &s) {
ll hash = 0;
for (char c : s) {