最短编辑距离
最短编辑距离
题干
给定 n 个长度不超过 10 的字符串以及 m 次询问,每次询问给出一个字符串和一个操作次数上限。
对于每次询问,请你求出给定的 n 个字符串中有多少个字符串可以在上限操作次数内经过操作变成询问给出的字符串。
每个对字符串进行的单个字符的插入、删除或替换算作一次操作。
输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含一个字符串,表示给定的字符串。
再接下来 m 行,每行包含一个字符串和一个整数,表示一次询问。
字符串中只包含小写字母,且长度均不超过 10。
输出格式
输出共 m 行,每行输出一个整数作为结果,表示一次询问中满足条件的字符串个数。
数据范围
1≤n, m≤1000
输入样例:
3 2
abc
acd
bcd
ab 1
acbd 2
输出样例:
1
3
解法
-
采用动态规划法,两层循环遍历。f[N][N]表示当前字符串状态。
-
伪代码:
if a[i] = a[j] // 字符相等,f状态只需要取左上角的状态(已经为最小次数)即可 f[i][j] = f[i - 1][j - 1]; else // 当前字符不相等,f要取左边、左上、上边三个状态的最小值,然后再+1(表示在前一状态基础上进行了一次变换) f[i][j] = min(f[i - 1][j - 1], min(f[i - 1][j], f[i][j - 1])) + 1;
-
代码:
#include<bits/stdc++.h> using namespace std; const int N = 1010; char a[N], b[N]; int n, m, f[N][N]; int main(){ scanf("%d", &n); scanf("%s", a + 1); scanf("%d", &m); scanf("%s", b + 1); for(int i = 1; i <= n; i ++) f[i][0] = i; for(int j = 1; j <= m; j ++) f[0][j] = j; for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++){ f[i][j] = min(f[i - 1][j - 1], min(f[i - 1][j], f[i][j - 1])) + 1; if(a[i] == b[j]) f[i][j] = f[i - 1][j - 1]; } printf("%d", f[n][m]); // printf("%d\n%s\n%d\n%s", n, a + 1, m, b + 1); return 0; }