题意:
给定串长<=100000的母串和n(n<=10)且长度<=10的小串,问哪一个小串在母串中通过增加删除修改一个字母的操作数(即编辑距离)最小变成母串中的substring。母串是一个环。
求最小的编辑距离,和对应字典序最小的字串。
分析:
比较明显的DP,编辑距离的变种。破环,在最后加倍。
因为数据特殊。对于小数据枚举+dp,大数据直接dp。【1】dp[i][j]裸的编辑距离
【2】f[i][j]表示母串中第i个位置,包含子串中到第j个位置时的距离。这里注意当母串长度小于子串时,比如aaa,aaaaa会出错。。。还不会怎么处理。
详见代码:


1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<string> 5 #include<algorithm> 6 #include<iostream> 7 8 using namespace std; 9 10 string str; 11 int n; 12 13 string seq[11]; 14 int ans[11]; 15 string tmp; 16 int dp[21][11]; 17 18 int calc(string a,string b)//DP,编辑距离 19 { 20 int la = a.length(); 21 int lb = b.length(); 22 dp[0][0] = 0; 23 for (int i=1;i<=la;i++) 24 dp[i][0] = i; 25 for (int j=1;j<=lb;j++) 26 dp[0][j] = j; 27 for (int i=1;i<=la;i++) 28 for (int j=1;j<=lb;j++) 29 { 30 if (a[i-1] == b[j-1]){ 31 dp[i][j] = dp[i-1][j-1]; 32 }else{ 33 dp[i][j] = dp[i-1][j-1] + 1; 34 } 35 dp[i][j] = min(dp[i][j],dp[i-1][j] + 1); 36 dp[i][j] = min(dp[i][j],dp[i][j-1] + 1); 37 } 38 int res = dp[1][lb]; 39 for (int i=1;i<=la;i++) 40 if (dp[i][lb] < res) 41 res = dp[i][lb]; 42 return res; 43 } 44 int solve(string b){//枚举+DP 45 int m = b.length(); 46 int res = m; 47 48 for (int s=0;s<n;s++) 49 { 50 tmp = ""; 51 int t = min(n,20); 52 for (int i=0;i<t;i++) 53 { 54 tmp = tmp + str[i+s]; 55 } 56 int ttt = calc(tmp,b); 57 if (ttt < res) 58 res = ttt; 59 } 60 61 return res; 62 } 63 64 int f[110010][14]; 65 66 int solll(string b){ 67 if (n < 100) 68 return solve(b);//小数据暴力枚举+DP 69 70 //这里无法才处理n < m的情况,所以这种数据暴力之。 71 72 f[0][0] = 0; 73 int m = b.length(); 74 for (int j=0;j<=m;j++) 75 f[0][j] = j; 76 int res = m; 77 int nn = n + min(2*m,n); 78 for (int i=1;i<=nn;i++) 79 { 80 for (int j=0;j<=m;j++) 81 f[i][j] = j;//每次都作为一个新的起点匹配。 82 for (int j=1;j<=m;j++) 83 { 84 if (str[i-1]==b[j-1]){ 85 f[i][j] = min(f[i][j],f[i-1][j-1]); 86 }else{ 87 f[i][j] = min(f[i][j],f[i-1][j-1]+1); 88 } 89 f[i][j] = min(f[i][j],f[i-1][j] + 1); 90 f[i][j] = min(f[i][j],f[i][j-1] + 1); 91 } 92 if (f[i][m] < res) 93 res = f[i][m]; 94 } 95 // printf(" %d\n",f[1][m]); 96 return res; 97 } 98 int main() 99 { 100 /* 101 n = 6; 102 str = "aaabbb"; 103 str = str + str; 104 string a = "aaabbb"; 105 string b = "bob"; 106 printf("%d\n",solve(b)); 107 printf("%d\n",solll(b)); 108 */ 109 while (cin>>str){ 110 n = str.length(); 111 str = str + str; 112 113 int nn; 114 scanf("%d",&nn); 115 for (int i=1;i<=nn;i++) 116 { 117 cin>>seq[i]; 118 ans[i] = solll(seq[i]); 119 // printf("%d\n",ans[i]); 120 } 121 for (int i=1;i<=nn;i++) 122 { 123 124 //ans[i] = solve(seq[i]); 125 } 126 127 string res = seq[1]; 128 int lll = ans[1]; 129 for (int i=2;i<=nn;i++){ 130 if (ans[i] < lll){ 131 lll = ans[i]; 132 res = seq[i]; 133 }else if (ans[i] == lll && seq[i] < res){ 134 res = seq[i]; 135 } 136 } 137 cout<<res<<" "<<lll<<endl; 138 } 139 return 0; 140 }
本文探讨了在环形母串中寻找与多个小串编辑距离最小的子串问题,提出了一种结合枚举和动态规划(DP)的算法。针对不同数据规模,算法采用不同的策略,对于小数据集使用枚举+DP,而大数据集直接应用DP。文章详细解释了编辑距离计算的DP过程,并展示了如何处理母串长度小于子串的特殊情况。
668

被折叠的 条评论
为什么被折叠?



