总匹配分数可以分为两部分计算:
暴力枚举所有 $K$ 个旋转需要 $O(K^2)$,太慢。我们需要 $O(K)$。
关键洞察: 如果数字 $X$ 在旋转 $R$ 后匹配,那么它们的原始索引差 $Index_B(X) - Index_A(X)$ 必然与 $R$ 有关。
统计每个位置差出现的频率 (Frequency Map),频率最高的就是最佳旋转。
#include
using namespace std;
typedef long long ll;
int n, k;
int a[500005], b[500005], seen[500005];
int pos[500005]; // 1-based index storage for Array A
int ans; // Count of items outside both cycles
// Core Logic: Calculate max matches for fixed orientation
int solve() {
vector v;
v.resize(k+1, 0); // Frequency bucket for shifts
for (int i = 1; i <= k; i++) {
if (pos[b[i]] == 0) continue; // Item in B not found in A
int d = i - pos[b[i]]; // Calculate shift difference
if (d < 0) d += k; // Handle circular wrap-around
v[d]++;
}
// Return the shift with the highest frequency
return *max_element(v.begin(), v.end());
}
int main() {
scanf("%d %d", &n, &k);
// Read A and mark seen
for (int i = 1; i <= k; i++) {
scanf("%d", &a[i]);
seen[a[i]] = 1;
}
// Read B and mark seen
for (int i = 1; i <= k; i++) {
scanf("%d", &b[i]);
seen[b[i]] = 1;
}
// Part 1: Count items NOT in either cycle (Always valid)
for (int i = 1; i <= n; i++)
if (!seen[i]) ans++;
// Precompute positions of elements in A for O(1) lookup
for (int i = 1; i <= k; i++)
pos[a[i]] = i;
// Part 2: Solve for original direction
int ans0 = solve();
// Part 3: Solve for reversed direction
reverse(b+1, b+k+1);
int ans1 = solve();
// Final Answer = Outside + Max(Inside_Original, Inside_Reversed)
printf("%d\n", ans + max(ans0, ans1));
return 0;
}
这个问题的核心是将“旋转匹配”问题转化为“统计相对位置差频率”的问题。
这种技巧在处理环形数组或周期性字符串匹配问题时非常常用。