线性dp:编辑距离

题目链接:https://www.acwing.com/problem/content/901/
题意:给定n个长度不超过10的字符串以及m次询问,每次询问给出一个字符串和一个操作次数上限。
对于每次询问,请你求出给定的n个字符串中有多少个字符串可以在上限操作次数内经过操作变成询问给出的字符串。
每个对字符串进行的单个字符的插入、删除或替换算作一次操作。
数据范围
1≤n,m≤1000,
输入样例:
3 2
abc
acd
bcd
ab 1
acbd 2
输出样例:
1
3
思路:显然这就是反复计算最短编辑距离了,再此就直接引用上一题的具体处理思路吧。

  • 状态表示:1.集合:所有将a[1 ~ i]变成b[1 ~ j] 的操作方式;2属性:这些操作方式的最小值
  • 状态计算:无非三种操作: (1) 删:删除a [ i ] 试得a[1 ~ i - 1] = b[1 ~ j ],即 f [i - 1 , j ] + 1 ; (2) 添加一个a [ i ] 使得 a[1 ~ i] = b [ j ],即f[ i , j - 1] + 1; (3) 修改a [ i ] 使得a[1 ~ i] = b [ j ],即f[ i - 1 , j - 1] + 1.
    代码实现:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<=n;i++)
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1005;
int n, m;
int f[MAXN][MAXN];
char str[MAXN][MAXN];
int edit_distance(char a[], char b[])
{
    int la = strlen(a + 1), lb = strlen(b + 1);
    for(int i = 0; i <= lb; i ++ ) f[0][i] = i;
    for(int i = 0; i <= la ; i ++ ) f[i][0] = i;
    for(int i = 1; i <= la; i ++ ){
        for(int j = 1; j <= lb; j ++ ){
            f[i][j] = min(f[i - 1][j] + 1, f[i][j - 1] + 1);
            f[i][j] = min(f[i][j], f[i - 1][j - 1] + (a[i] != b[j]));
        }
    }
    return f[la][lb];
}
int main()
{
    scanf("%d%d",&n, &m);
    for(int i = 0; i < n; i ++ )
        scanf("%s",str[i] + 1);
    while(m -- ){
        char s[MAXN];
        int t;
        scanf("%s%d",s + 1, &t);
        int ans = 0;
        for(int i = 0; i < n; i ++ )
            if(edit_distance(str[i], s) <= t)
                ans ++ ;
        printf("%d\n",ans);
    }
    return 0;
}

发布了61 篇原创文章 · 获赞 0 · 访问量 978

猜你喜欢

转载自blog.csdn.net/Satur9/article/details/104034958