编辑距离
编辑距离
例题
给定 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
题解
-
分析:
仔细观察不难发现:其实这只是在最短编辑距离的基础上加了一些多重循环而已,处理过程上麻烦了一些,但是思路还是很简单的,只需要仔细认真查看好即可。
-
避坑:
先来记个结论:
全局int、double数组默认为0;
非全局数组初值是机器垃圾值。
刚开始我把f[][]数组定义在了函数内,即变成了局部数组。这就导致f[0][0]变成了一个随机数。
对于非全局变量而言,虽然初始化都是垃圾值(随机值),但一般机器内数组定义长度比较大时数组所有值会被默认初始为0(至少目前我自己测试了几台机器确实是这样的)。
-
代码:
#include<bits/stdc++.h> using namespace std; const int N = 1005; char a[N][12]; int n, m; int f[12][12]; int fun(char a[], char b[]){ int la, lb; la = lb = 0; for(int i = 1; a[i] != '\0'; i ++){ la ++; f[i][0] = i; } for(int i = 1; b[i] != '\0'; i ++){ lb ++; f[0][i] = i; } // int la = strlen(a + 1); // int lb = strlen(b + 1); for(int i = 1; i <= la; i ++) f[i][0] = i; for(int i = 1; i <= lb; i ++) f[0][i] = i; // printf("%d ****\n", f[0][0]); for(int i = 1; i <= la; i ++){ for(int j = 1; j <= lb; j ++){ if(a[i] == b[j]) f[i][j] = f[i - 1][j - 1]; else f[i][j] = min(f[i - 1][j - 1], min(f[i][j - 1], f[i - 1][j])) + 1; } } return f[la][lb]; } int main(){ scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) scanf("%s", a[i] + 1); while(m --){ char b[11]; int q; scanf("%s%d", b + 1, &q); int cnt = 0; for(int i = 1; i <= n; i ++){ if(fun(b, a[i]) <= q) cnt ++; } printf("%d\n", cnt); } return 0; }