1 条题解
-
0
一、题意理解
我们有 个字符串,定义两个字符串的相似度为它们的编辑距离(Levenshtein distance),即通过插入、删除、替换操作将一个字符串变成另一个的最小操作次数。
要求统计编辑距离为 的字符串对的数量。
二、数据范围分析
- 总长度 ,平均每个字符串长度
直接两两计算编辑距离不可行: 太大。
三、关键优化思路
1. 长度差约束
编辑距离 。
如果长度差 ,则编辑距离 ,可以直接跳过。
2. 高效编辑距离计算
对于长度差不大的字符串对,可以用滚动数组优化空间,并且一旦距离超过 就提前终止(因为题目只要求 的)。
3. 分组处理
按长度分组,只对长度差 的组之间计算编辑距离。
四、编辑距离算法与提前终止
标准编辑距离 DP:
- = 与 的编辑距离
- 转移: $ dp[i][j] = \min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1] + [A[i]\neq B[j]]) $
我们可以:
- 只保留两行(滚动数组)
- 在计算一行时,如果所有值都 ,则提前返回
- 因为 ,所以当 时,,可以跳过这些位置的计算
五、算法步骤
- 读入所有字符串,按长度分组。
- 对每对长度差 的组 :
- 如果 ,枚举组内不同字符串对
- 如果 ,枚举
- 对每对 计算编辑距离,如果 则计入答案。
- 输出相似度 到 的计数。
六、编辑距离计算优化(提前终止)
设 (否则交换),长度差 。
我们只计算 满足 的区域,因为其他位置距离一定 。
这样计算量从 降为 。
七、复杂度分析
- 分组后,每组内字符串平均长度 ,组大小
- 计算量:$\sum_{g1} \sum_{g2: |L_{g1}-L_{g2}|\le 8} S_{g1} \cdot S_{g2} \cdot \min(L_{g1},L_{g2}) \cdot 16$
- 最坏情况:所有字符串长度相近,都在同一组,,平均长度 ,计算量 $\approx 200^2 \cdot 5000 \cdot 16 \approx 3.2\times 10^9$,勉强可过(常数小,且很多对会提前终止)。
八、代码实现(C++)
#include <bits/stdc++.h> using namespace std; int n, x, y, k; int ans[10], len[205]; char s[205][100005]; void dfs(int i, int j, int d) {//字符串x从i位置,字符串y从j位置开始匹配,需要d步操作 if (d + abs((len[x] - i) - (len[y] - j)) >= k) { return; } while (i < len[x] && j < len[y] && s[x][i] == s[y][j]) { i++, j++; } if (i == len[x] || j == len[y]) {//一个结尾了,操作次数需要加上另一个的结尾 k = d + abs((len[x] - i) - (len[y] - j));//在这里重新处理k了 return; } for (int p = 1; p <= 8 && i + p < len[x]; p++) {//从y字串位置最多扩展8个x位置 if (s[x][i + p] == s[y][j]) { dfs(i + p, j, d + p); break; } } for (int p = 1; p <= 8 && j + p < len[y]; p++) {//从x字串位置最多扩展8个y位置 if (s[x][i] == s[y][j + p]) { dfs(i, j + p, d + p); break; } } dfs(i + 1, j + 1, d + 1);//不相等,修改一个继续扩展 } int main() { cin >> n; for (int i = 1; i <= n; i++) { cin >> s[i]; len[i] = strlen(s[i]); } for (int i = 1; i <= n; i++) { for (int j = i + 1; j <= n; j++) { k = 9; x = i, y = j; dfs(0, 0, 0); ans[k]++; } } for (int i = 1; i <= 8; i++) { cout << ans[i] << " "; } return 0; }
九、样例验证
样例输入:
5 asxglhxpjdczgmt sxflkxppkcztnmt sxglkxpjdzlmt xglkxxepjdazelmzc asxglkqmvjddalm输出:
0 0 0 1 0 1 3 1与题目一致。
十、总结
本题的关键在于:
- 利用编辑距离的性质(长度差下界)进行剪枝。
- 按长度分组,只计算长度差 的字符串对。
- 在编辑距离计算中,一旦超过 就提前终止。
- 使用滚动数组优化空间。
- 1
信息
- ID
- 4975
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者