c++写:小胡虽然在儿童节小挣了一笔,但是记录过消费后,他发现自己得开源节流了。所以他买了好多只小鸡仔,通过养鸡来增加收入。 但是这些小鸡实在是太吵了,整天叽叽叽个不停,小胡被吵得神经衰弱,都快产生幻听了,只觉得一串一串的回声在脑子里盘旋。 声音化作了两串字符串,表示他听到的叽叽声,两串声音中最长的重复部分就是他的幻听。 最长重复部分指的是:从一个字符串第一个字符开始的连续字符串和从另一个字符串最后一个字符开始的连续字符串,完全相同的最大长度。 例如以下两串叽叽声: aNBHhjsada jsadasdfdfdfdfdaNB 第一个字符串的前缀 aNB 和第二个字符串的后缀相同; 第一个字符串的后缀 jsada 和第二个字符串的前缀相同; 而 jsada 比较长,所以最长的重复部分长度为 5 5。
时间: 2024-03-25 08:42:08 浏览: 126
好的,这是一个字符串匹配问题,可以使用哈希和二分的方法来解决。具体思路如下:
1. 定义一个哈希函数,将字符串转换为一个唯一的哈希值。
2. 定义一个二分函数,用来判断重复部分的长度。
3. 对于第一个字符串的每一个前缀,计算其哈希值,并将其存储在一个哈希表中。
4. 对于第二个字符串的每一个后缀,计算其哈希值,并在哈希表中查找是否有相同的哈希值。
5. 如果有相同的哈希值,则调用二分函数,判断重复部分的长度,并更新最大值。
6. 最后输出最大值即可。
下面是一份示例代码,供你参考:
```c++
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
typedef long long LL;
const LL P = 131; // 哈希函数中的质数
const int MAXN = 100010; // 字符串最大长度
int n, m;
string s1, s2;
LL h[MAXN], p[MAXN]; // 哈希函数和幂次
// 计算字符串的哈希值
LL get_hash(string &s) {
LL res = 0;
for (int i = 0; i < s.length(); i++) {
res = (res * P + s[i]) % LLONG_MAX;
}
return res;
}
// 二分函数,判断重复部分的长度
int check(int len) {
unordered_map<LL, int> hash; // 哈希表
int res = 0;
LL h1 = 0, h2 = 0; // 分别表示第一个字符串和第二个字符串的哈希值
p[0] = 1;
for (int i = 1; i <= len; i++) {
h1 = (h1 * P + s1[i - 1]) % LLONG_MAX;
h2 = (h2 + s2[m - i] * p[i - 1]) % LLONG_MAX;
p[i] = p[i - 1] * P % LLONG_MAX;
}
hash[h1] = len; // 将第一个字符串的前缀哈希值存储到哈希表中
for (int i = len + 1; i <= n; i++) {
h1 = (h1 * P + s1[i - 1]) % LLONG_MAX; // 计算下一个前缀的哈希值
h1 = (h1 - s1[i - len - 1] * p[len]) % LLONG_MAX; // 减去上一个前缀的哈希值
if (h1 < 0) h1 += LLONG_MAX; // 防止负数出现
if (hash.count(h1)) { // 如果哈希表中有相同的哈希值
int j = hash[h1];
if (i - j <= len) { // 判断是否为重复部分
res = max(res, i - j);
}
}
h2 = (h2 * P + s2[m - i + len]) % LLONG_MAX; // 计算下一个后缀的哈希值
h2 = (h2 - s2[m - i] * p[len]) % LLONG_MAX; // 减去上一个后缀的哈希值
if (h2 < 0) h2 += LLONG_MAX; // 防止负数出现
hash[h2] = i; // 将后缀的哈希值存储到哈希表中
}
return res;
}
int main() {
cin >> s1 >> s2;
n = s1.length();
m = s2.length();
int l = 0, r = min(n, m);
while (l < r) { // 二分查找最长重复部分的长度
int mid = (l + r + 1) / 2;
if (check(mid) >= mid) {
l = mid;
} else {
r = mid - 1;
}
}
cout << l << endl; // 输出最长重复部分的长度
return 0;
}
```
阅读全文