整理字符串处理.docx
- 文档编号:3043004
- 上传时间:2022-11-17
- 格式:DOCX
- 页数:15
- 大小:61.11KB
整理字符串处理.docx
《整理字符串处理.docx》由会员分享,可在线阅读,更多相关《整理字符串处理.docx(15页珍藏版)》请在冰豆网上搜索。
整理字符串处理
五、字符串编辑距离
给定一个源字符串和目标字符串,能够对源串进行如下操作:
1.在给定位置上插入一个字符
2.替换任意字符
3.删除任意字符
求通过以上操作使得源字符串和目标字符串一致的最小操作步数。
简单描述一下解该题的思想,源字符串和目标字符串分别为str_a、str_b,二者的长度分别为la、lb,定义f[i,j]为子串str_a[0...i]和str_b[0...j]的最小编辑距离,简单分析可知求得的str_a[0...i]和str_b[0...j]的最小编辑距离有一下三种可能:
(1)去掉str_a[0...i]的最后一个字符跟str_b[0...j]匹配,则f[i, j]的值等于f[i-1, j]+1;
(2)去掉str_b[0...j]的最后一个字符跟str_a[0...i]匹配,则f[i, j]的值等于f[i, j-1]+1;
(3)去掉str_a[0...i]和str_b[0...j]的最后一个字符,让二者匹配求得f[i-1, j-1],计算f[i, j]时要考虑当前字符是否相等,如果str_a[i]==str_b[j]说明该字符不用编辑,所以f[i, j]的值等于f[i-1, j-1],如果str_a[i]!
=str_b[j]说明该字符需要编辑一次(任意修改str_a[i]或者str_b[j]即可),所以f[i, j]的值等于f[i-1, j-1]+1。
因为题目要求的是最小的编辑距离,所以去上面上中情况中的最小值即可,因此可以得到递推公式:
f[i, j] = Min ( f[i-1, j]+1, f[i, j-1]+1, f[i-1, j-1]+(str_a[i]==str_b[j] ?
0 :
1) )
维基百科中的描述如下:
1)递归方法(用到动态规划)
由上述的递归公式可以有以下代码:
[cpp] viewplaincopy
1.//求两个字符串的编辑距离问题
2.//递归版本,备忘录C[i,j]表示strA[i]...strA[size_A-1]与strB[j]...strB[size_B-1]的编辑距离
3.int editDistance_mem(char *strA,int size_A,char *strB,int size_B){
4. int **C=new int*[size_A+1];
5. for(int i=0;i<=size_A;i++){
6. C[i]=new int[size_B+1]();
7. }
8. //初始化
9. for(int i=0;i<=size_A;i++){
10. for(int j=0;j<=size_B;j++)
11. C[i][j]=INT_MAX;
12. }
13. int res=EDM(C,strA,0,size_A-1,strB,0,size_B-1);
14. //free mem
15. for(int i=0;i<=size_A;i++){
16. delete [] C[i];
17. }
18. delete [] C;
19. return res;
20.}
21.int EDM(int **C,char *strA,int i,int A_end,char *strB,int j,int B_end){
22. if(C[i][j] 23. return C[i][j]; 24. if(i>A_end){ 25. if(j>B_end) 26. C[i][j]=0; 27. else 28. C[i][j]=B_end-j+1; 29. }else if(j>B_end){ 30. if(i>A_end) 31. C[i][j]=0; 32. else 33. C[i][j]=A_end-i+1; 34. } 35. else if(strA[i]==strB[j]) 36. C[i][j]=EDM(C,strA,i+1,A_end,strB,j+1,B_end); 37. else{ 38. int a=EDM(C,strA,i+1,A_end,strB,j+1,B_end); 39. int b=EDM(C,strA,i,A_end,strB,j+1,B_end); 40. int c=EDM(C,strA,i+1,A_end,strB,j,B_end); 41. C[i][j]=min(a,b,c)+1; 42. } 43. return C[i][j]; 44.} 2)矩阵标记法 递推方法(也可称为矩阵标记法),通过分析可知可以将f[i, j]的计算在一个二维矩阵中进行,上面的递推式实际上可以看做是矩阵单元的计算递推式,只要把矩阵填满了,f[la-1, lb-1]的值就是要求得最小编辑距离。 代码如下: [cpp] viewplaincopy 1.//求两个字符串的编辑距离问题 2.//递推版本 C[i,j]表示strA[i]...strA[size_A-1]与strB[j]...strB[size_B-1]的编辑距离 3.int editDistance_iter(char *strA,int size_A,char *strB,int size_B){ 4. int **C=new int*[size_A+1]; 5. for(int i=0;i<=size_A;i++){ 6. C[i]=new int[size_B+1](); 7. } 8. for(int i=size_A;i>=0;i--){ 9. for(int j=size_B;j>=0;j--){ 10. if(i>size_A-1){ 11. if(j>size_B-1) 12. C[i][j]=0; 13. else 14. C[i][j]=size_B-j; 15. }else if(j>size_B-1){ 16. if(i>size_A-1) 17. C[i][j]=0; 18. else 19. C[i][j]=size_A-i; 20. }else if(strA[i]==strB[j]) 21. C[i][j]=C[i+1][j+1]; 22. else 23. C[i][j]=min(C[i+1][j+1],C[i+1][j],C[i][j+1])+1; 24. } 25. } 26. int res=C[0][0]; 27. //free mem 28. for(int i=0;i<=size_A;i++){ 29. delete [] C[i]; 30. } 31. delete [] C; 32. return res; 33.} 六、最长不重复子串 很好理解,即求一个串内最长的不重复子串。 1)使用Hash 要求子串中的字符不能重复,判重问题首先想到的就是hash,寻找满足要求的子串,最直接的方法就是遍历每个字符起始的子串,辅助hash,寻求最长的不重复子串,由于要遍历每个子串故复杂度为O(n^2),n为字符串的长度,辅助的空间为常数hash[256]。 代码如下: [cpp] viewplaincopy 1./* 最长不重复子串 我们记为 LNRS */ 2.int maxlen; 3.int maxindex; 4.void output(char * arr); 5./* LNRS 基本算法 hash */ 6.char visit[256]; 7.void LNRS_hash(char * arr, int size) 8.{ 9. for(int i = 0; i < size; ++i) 10. { 11. memset(visit,0,sizeof(visit)); 12. visit[arr[i]] = 1; 13. for(int j = i+1; j < size; ++j) 14. { 15. if(visit[arr[j]] == 0) 16. { 17. visit[arr[j]] = 1; 18. } 19.else 20. { 21. if(j-i > maxlen) 22. { 23. maxlen = j - i; 24. maxindex = i; 25. } 26. break; 27. } 28. } 29. } 30. output(arr); 31.} 2)动态规划法 字符串的问题,很多都可以用动态规划处理,比如这里求解最长不重复子串,和前面讨论过的最长递增子序列问题就有些类似,在LIS(最长递增子序列)问题中,对于当前的元素,要么是与前面的LIS构成新的最长递增子序列,要么就是与前面稍短的子序列构成新的子序列或单独构成新子序列。 这里我们采用类似的思路: 某个当前的字符,如果它与前面的最长不重复子串中的字符没有重复,那么就可以以它为结尾构成新的最长子串;如果有重复,那么就与某个稍短的子串构成新的子串或者单独成一个新子串。 我们来看看下面两个例子: 1)字符串“abcdeab”,第二个a之前的最长不重复子串是“abcde”,a与最长子串中的字符有重复,但是它与稍短的“bcde”串没有重复,于是它可以与其构成一个新的子串,之前的最长不重复子串“abcde”结束; 2)字符串“abcb”,跟前面类似,最长串“abc”结束,第二个字符b与稍短的串“c”构成新的串; 我们貌似可以总结出一些东西: 当一个最长子串结束时(即遇到重复的字符),新的子串的长度是与(第一个重复的字符)的下标有关的。 于是类似LIS,对于每个当前的元素,我们“回头”去查询是否有与之重复的,如没有,则最长不重复子串长度+1,如有,则是与第一个重复的字符之后的串构成新的最长不重复子串,新串的长度便是当前元素下标与重复元素下标之差。 可以看出这里的动态规划方法时间复杂度为O(N^2),我们可以与最长递增子序列的动态规划方
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 整理 字符串 处理