https://niumacode.com/training/173/problem/P1802
两个点
:答案的排序(二叉堆的重载定义)、字符串最小距离(操作数)
对于处理两个字符串直接经过多少次操作才能变换得到
dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
两种情况
1.对应位置字符不相同,则需要经过操作从减去对应操作的字符dp并+step
2.对应位置字符相同(无操作),则从两字符串同时减去这个字符的dp得到
#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;
struct node{
int val;
string key;
bool operator<(const node& other) const {
if (val != other.val) {
return val > other.val; // 距离小的优先
} else {
return key > other.key; // 距离相同,字母序小的优先(a < b,所以a>b为false,a先出队)
}
}
};
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
for (int i = 1; i <= word1.size(); i++) {
for (int j = 1; j <= word2.size(); j++) {
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
}
else {
dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
}
}
}
return dp[word1.size()][word2.size()];
}
int main() {
int cnt,n;
cin>>cnt>>n;
vector<string>orders(n);
int num=0;
for(int i=0;i<n;i++){
cin>>orders[i];
}
string user;
cin>>user;
priority_queue<node> pq;
for(int i=0;i<n;i++){
string s=orders[i];
if(s==user) {cout<<user<<endl;
continue;}
int need=minDistance(user,s);
if(need<=cnt){
pq.push({need,s});
num++;
}
}
while(!pq.empty()){
auto& ans=pq.top();
cout<<ans.key<<" ";
pq.pop();
}
if(num==0) cout<<"None"<<endl;
//即对每个命令,用户输入的是否能成为cnt变换下的子序列
}
// 64 位输出请用 printf("%lld")
该解法通过以下两点保证子序列顺序不变:
状态定义:dp[i][j] 仅统计 s 前 i 个字符按顺序在 t 前 j 个字符中出现的长度。
转移逻辑:匹配时只能用 t 中当前位置或之前的字符,且只能 “向前匹配”(不能回溯 t 的位置),确保 s 的字符顺序与在 t 中出现的顺序一致。
浙公网安备 33010602011771号