特殊的编辑距离
Posted 顾文繁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了特殊的编辑距离相关的知识,希望对你有一定的参考价值。
在自然语言处理的过程中,经常需要判断一个字符串和另外一个字符串之间的一个相似程度,其中常见的一个指标就是编辑距离,即一个字符串最少经过多少次“增删改”某个字符,可以变为另一个字符串。如“abc”与“ac”的编辑距离为1,是因为在a和c中间“增加”一个b即可。如“abcd”与“axc”的编辑距离为2,是因为把“abcd”的b修改为x,然后再删除d即可,共2次操作。但是在某种场景中,编辑距离定义为词粒度的。比如句子A “I am a coder”与句子B “hello , I am a singer”之间,对于句子A可以通过添加"hello"和符号",", 并替换"coder"为"singer",共3个操作得到句子B。所以可得其基本的编辑距离为3。在本题中,特别地,对于部分词,比如标点符号“, ”、"hello"对于句子语义的影响并不重要,这部分称之为停用词,这部分可以在匹配的过程中被跳过。比如对于句子A “I am a coder”与句子B “hello , I am a singer”,如果加入了停用词的影响,那编辑距离从3降到1。所以目标是可以有选择性地跳过停用词的情况下,问最小的编辑距离是多少。
输入描述:
共3行
第一行为停用词列表,用空格区分
第二行为句子A,所有词可以用空格区分,词数不超过10000
第三行为句子B,所有词可以用空格区分,词数不超过10000
此题是一个动规二维动态规划问题。单词有停用词,所以要开始动规之前需要进行预处理,将两个字符出现的停用词去掉。
动规三部法:
1.明确dp[i][j]的含义,即前A中第i个单词,前B中第j个单词的最小编辑距离。
2.明确转移方程:
当前A第i个单词和B第j个单词的最小编辑距离为:
1.1如果两个词不同,dp[i][j]可能为修改一个单词的最小编辑为dp[i-1][j-1]+1,或者删除A中第i个单词/B中第j个单词所出现的最小编辑距离,他们之间的最小值。
1.2如果两个词相同,dp[i][j] = dp[i-1][j-1],这个很好理解。即忽略当前相同的词,取上个词语的最小编辑距离。
3.初始化
当第0个单词时,无论第0列还是第0行都是其行数(单词数量)。因为,A中0个单词和B中第1,2,3,4,5…单词匹配,需要的最小编辑距离就是1.2,3,4…
C++实现
#include <bits/stdc++.h>
using namespace std;
int main()
unordered_set<string> stop;
string word;
vector<string> A,B;
while(cin >> word)
stop.insert(word);
if(cin.get() == '\\n') break;
for(int i = 0;i < 2;i++)
while(cin >> word)
if(stop.count(word)) continue;
if(i == 0)
A.push_back(word);
else
B.push_back(word);
if(cin.get() == '\\n') break;
int n1 = A.size();
int n2 = B.size();
//dp的内涵:dp[i][j] ,A中第i个单词,B中第j个单词的最小编辑距离
vector<vector<int>> dp(n1+1, vector<int>(n2+1, 0));
for(int i = 1;i <= n1;i++) dp[i][0] = i;
for(int i = 1;i <= n2;i++) dp[0][i] = i;
for(int i = 1;i <= n1;i++)
for(int j = 1;j <= n2;j++)
if(A[i-1] == B[j-1])
dp[i][j] = dp[i-1][j-1];
else // 两个字符串不一致,从 删除A中的当前单词或者删除B中的当前单词,或者调整其中一个单词。
dp[i][j] = 1 + min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]));
cout << dp[n1][n2] << endl;
return 0;
以上是关于特殊的编辑距离的主要内容,如果未能解决你的问题,请参考以下文章