假设字符串s采用顺序串储存,设计一个基于BF的算法,在串s中查找子串t最后一次出现的位置。例如,当s=“abcdabcd”,t=“abc”时
时间: 2024-10-20 19:09:44 浏览: 45
要在字符串 `s` 中使用基于Boyer-Moore (BM) 字符串搜索算法查找子串 `t` 的最后一次出现位置,Boyer-Moore算法利用了字符不匹配后的跳过规则,能够提高搜索效率。这里我们将描述基本步骤:
1. **预处理**:
- 计算后缀偏移数组(Bad Character Shifts, BCS)和好后缀表(Good Suffix Table, GST)。BCS用于根据单个字符的不匹配情况快速跳过部分字符串;GST则记录了从每个位置开始到结束处最长公共前后缀的长度,以便于发生前缀冲突时定位。
2. **主搜索**:
- 初始化两个指针,`i` 和 `j` 分别代表子串 `t` 的起始位置和 `s` 的当前位置。
- 检查 `t[j]` 是否等于 `s[i]`,如果相等,则递增 `j`(表示继续匹配)。
- 如果不相等,先尝试使用BCS通过移动 `i` 来避免无效比较,然后检查是否发生了前缀冲突(即 `t[j:]` 已经出现了多次),此时利用GST更新 `i`。
- 当 `j` 等于子串 `t` 的长度时,找到的子串 `t` 的起始位置就是 `i`。
以下是一个简单的伪代码示例:
```cpp
// 假设 s 和 t 是字符串,n = t.length()
void boyer_moore_search(const string &s, const string &t) {
int n = t.size();
vector<int> bcs(t.size(), 0), gst(s.size() + 1, 0);
// 初始化BCS和GST
for (int i = 1; i < t.size(); ++i) {
while (t[t.size() - i - 1] != t[t.size() - i]) {
bcs[i] = max(bcs[i], 1);
}
}
for (int len = 1; len <= n; ++len) {
for (int i = n - len; i >= 0; --i) {
if (t.substr(i, len) == t.substr(0, len)) {
gst[len] = i;
} else {
break;
}
}
}
int i = n - 1, j = n - 1;
while (i >= 0) {
if (s[i] == t[j]) {
--i;
--j;
} else {
int skip = n - min(gst[j - i], bcs[j]);
i -= skip;
j -= skip;
}
if (j < 0) {
break;
}
}
// i现在指向的是子串 t 最后一次出现的位置(减去1)
if (i >= 0) {
cout << "Last occurrence of '" << t << "' in '"
<< s << "' is at position " << i + 1 << endl;
} else {
cout << "Substring not found" << endl;
}
}
```
阅读全文