后缀自动机构建:首先为第一个字符串构建后缀自动机。后缀自动机是一种高效的数据结构,能够表示一个字符串的所有子串,并允许在后续处理中快速查找子串。
遍历第二个字符串:使用构建好的后缀自动机,逐个字符处理第二个字符串。维护当前状态和当前匹配长度,通过后缀自动机的转移和后缀链接来更新状态,记录最长公共子串的长度。 ****
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
struct State {
int len;
int link;
int next[26];
State() : len(0), link(-1) {
memset(next, -1, sizeof(next));
}
};
vector<State> sa;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s, t;
cin >> s >> t;
// 构建第一个字符串的后缀自动机
sa.emplace_back(); // 根节点在索引0
int last = 0;
int size = 1;
for (char ch : s) {
int idx = ch - 'a';
int cur = size++;
sa.emplace_back();
sa[cur].len = sa[last].len + 1;
int p = last;
while (p != -1 && sa[p].next[idx] == -1) {
sa[p].next[idx] = cur;
p = sa[p].link;
}
if (p == -1) {
sa[cur].link = 0;
} else {
int q = sa[p].next[idx];
if (sa[p].len + 1 == sa[q].len) {
sa[cur].link = q;
} else {
int clone = size++;
sa.emplace_back();
sa[clone].len = sa[p].len + 1;
sa[clone].link = sa[q].link;
memcpy(sa[clone].next, sa[q].next, sizeof(sa[q].next));
while (p != -1 && sa[p].next[idx] == q) {
sa[p].next[idx] = clone;
p = sa[p].link;
}
sa[q].link = clone;
sa[cur].link = clone;
}
}
last = cur;
}
// 处理第二个字符串,计算最长公共子串长度
int max_len = 0;
int current = 0;
int current_len = 0;
for (char ch : t) {
int idx = ch - 'a';
while (current != 0 && sa[current].next[idx] == -1) {
current = sa[current].link;
current_len = sa[current].len;
}
if (sa[current].next[idx] != -1) {
current = sa[current].next[idx];
current_len++;
if (current_len > max_len) {
max_len = current_len;
}
} else {
current_len = 0;
}
}
cout << max_len << endl;
return 0;
}