1 条题解
-
0
题目分析
题意
我们需要找出所有登录名对,这些登录名对之间的不超过给定的阈值。这里的编辑距离包括四种操作:
1.删除字符 2. 插入字符 3. 替换字符 4. 交换相邻字符
输入输出要求
- 输入:多组数据,每组包含个登录名和距离阈值
- 输出:所有满足距离的登录名对,按字典序排序,并输出总对数
解题思路
关键点
- 编辑距离计算:需要实现一个能够处理四种操作的编辑距离算法
- 高效比较:对于,的算法是可行的
- 排序输出:需要按字典序输出结果
算法选择
使用动态规划计算扩展的编辑距离,处理四种操作:
- 标准编辑距离(插入、删除、替换)
- 额外处理相邻交换的情况
代码分析
数据结构
struct cstr { char s[22]; bool operator <(const cstr& c)const { return strcmp(s,c.s)<0; } }st[205];存储登录名,并重载<运算符用于排序
核心函数
int dp(char *s1, char *s2) { int l1 = strlen(s1), l2 = strlen(s2); memset(d, 0, sizeof d); // 初始化边界条件 for(int i=1; i<=l2; i++) d[0][i] = i; // 全插入 for(int i=1; i<=l1; i++) d[i][0] = i; // 全删除 for(int i=1; i<=l1; i++) { for(int j=1; j<=l2; j++) { d[i][j] = INF; // 标准编辑距离操作 if(s1[i-1] == s2[j-1]) { d[i][j] = d[i-1][j-1]; // 字符相同 } else { // 取插入、删除、替换的最小值 d[i][j] = min(d[i][j-1], min(d[i-1][j], d[i-1][j-1])) + 1; } // 处理交换操作 if(i>=2 && j>=2 && s1[i-2]==s2[j-1] && s1[i-1]==s2[j-2]) { d[i][j] = min(d[i][j], d[i-2][j-2]+1); // 交换相邻字符 } // 处理更复杂的交换情况 if(i>=2 && j>=3 && s1[i-2]==s2[j-1] && s1[i-1]==s2[j-3]) { d[i][j] = min(d[i][j], d[i-2][j-3]+2); } if(i>=3 && j>=2 && s1[i-1]==s2[j-2] && s1[i-3]==s2[j-1]) { d[i][j] = min(d[i][j], d[i-3][j-2]+2); } } } return d[l1][l2]; }主流程
1.读取输入并排序 2.双重循环比较所有登录名对 3. 输出符合条件的对
复杂度分析
- 时间复杂度:,其中是字符串最大长度()
- 空间复杂度:
示例解析
对于输入:
8 2 omura toshio raku tanaka imura yoshoi hayashi miura程序会: 1.排序所有登录名 2. 计算每对之间的距离 3. 输出距离的对
边界情况
- 空字符串
- 完全相同的字符串(距离)
- 最大长度字符串(字符)
- 时只输出完全相同的对
总结
这个解决方案通过动态规划高效计算了扩展的编辑距离,并正确处理了所有操作。排序和双重循环确保了结果的正确性和有序性。
标程
#include <cstdio> #include <string.h> #include <algorithm> #define INF 0x3fffffff using namespace std; struct cstr{ char s[22]; bool operator <(const cstr& c)const{ return strcmp(s,c.s)<0; } }st[205]; int n,dis,d[20][20]; int dp(char *s1,char *s2){ int l1=strlen(s1),l2=strlen(s2); memset(d,0,sizeof d); for(int i=1;i<=l2;i++)d[0][i]=i; for(int i=1;i<=l1;i++)d[i][0]=i; for(int i=1;i<=l1;i++){ for(int j=1;j<=l2;j++){ d[i][j]=INF; if(s1[i-1]==s2[j-1]){ d[i][j]=d[i-1][j-1]; }else{ d[i][j]=min(d[i][j-1],min(d[i-1][j],d[i-1][j-1]))+1; } if(i>=2&&j>=2&&s1[i-2]==s2[j-1]&&s1[i-1]==s2[j-2]){ d[i][j]=min(d[i][j],d[i-2][j-2]+1); } if(i>=2&&j>=3&&s1[i-2]==s2[j-1]&&s1[i-1]==s2[j-3]){ d[i][j]=min(d[i][j],d[i-2][j-3]+2); } if(i>=3&&j>=2&&s1[i-1]==s2[j-2]&&s1[i-3]==s2[j-1]){ d[i][j]=min(d[i][j],d[i-3][j-2]+2); } } } return d[l1][l2]; } int main(){ // freopen("test.in","r",stdin); while(scanf("%d",&n),n){ scanf("%d",&dis); for(int i=0;i<n;i++)scanf("%s",st[i].s); sort(st,st+n); int tot=0; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ int x=dp(st[i].s,st[j].s); if(x<=dis){ tot++; printf("%s,%s\n",st[i].s,st[j].s); } } } printf("%d\n",tot); } return 0; }
- 1
信息
- ID
- 1147
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者