串的匹配算法--C語言實現
阿新 • • 發佈:2019-02-09
kmp算法 前綴 %d str 數值 它的 pos 我只 不存在
串這種數據結構,使用是比較多的,但是它的一些方法在更高級的語言中,比如Java,Python中封裝的比較完整了。在這裏,我只寫了串中使用最多的匹配算法,即串的定位操作。串的匹配算法常用的兩種就是樸素匹配算法和KMP匹配算法。代碼親測,可直接執行。
1 #include<stdio.h> 2 3 /*字符串長度*/ 4 int StringLength(char *L) 5 { 6 int i = 0; //記錄位置 7 int count = 0; //計數器,記錄長度 8 while(L[i]) //判斷當前位置是否為空 9 { 10 count++; //長度加1 11 i++; //計數器加1 12 } 13 return count; //返回長度 14 } 15 16 /*樸素匹配算法*/ 17 int Index(char *S, char *T) //S為主串,T為子串 18 { 19 int Slength = StringLength(S); //獲得主串S的長度 20 int Tlength = StringLength(T); //獲得子串T的長度 21 int i = 0; //記錄主串S當前位置 22 int j = 0; //記錄子串T當前位置 23 // int count = 0; 24 printf("樸素匹配算法中j回溯的值為:"); 25 while(i < Slength && j < Tlength) //確保兩個字符串的當前位置均小於其長度 26 { 27 // printf("%d ", j); 28 // count++; 29 if(S[i] == T[j]) //判斷主串S當前位置與子串T當前位置的字符是否相等 30 { 31 i++; //主串S的當前位置加1(後移) 32 j++; //子串T的當前位置加1(後移) 33 } 34 else //如果兩字符串的當前位置字符不等 35 { 36 i = i - j + 1; //主串S的當前位置i回溯到j==0時i位置的下一位置 37 j = 0; //子串T的當前位置j歸0 38 } 39 } 40 // printf("\nj共變化了%d次\n", count); 41 //循環比較完畢 42 if(j == Tlength) //判斷位置j的數值是否與子串T的長度相等 43 return i - Tlength; //若是,說明搜索成功,返回T在S中出現的首位置 44 else 45 return -1; //若不是,說明T不存在與S中,返回-1 46 } 47 48 /*KMP算法*/ 49 void Get_Next(char *T, int next[]) 50 { 51 int Tlength = StringLength(T); //獲得字符串T的長度 52 int i = 0; //T的後綴位置 53 int j = -1; //T的前綴位置 54 next[0] = -1; //next數組的首位賦值為-1 55 while(i < Tlength) //確保後綴位置小於串長 56 { 57 if(j == -1 || T[i] == T[j]) //如果j==-1,說明前綴已經回退到最前方 58 { //如果T[i] == T[j],說明當前前綴與後綴相等 59 i++; //則後綴位置後移一位 60 j++; //前綴位置後移一位 61 next[i] = j; //當前後綴位置的next值為j 62 } 63 else 64 j = next[j]; //否則,j回退(還沒完全搞懂回退到哪) 65 } 66 } 67 68 int Index_KMP(char *S, char *T) 69 { 70 int Slength = StringLength(S); //獲得主串S的長度 71 int Tlength = StringLength(T); //獲得子串T的長度 72 int i = 0; //記錄S的當前位置 73 int j = 0; //記錄T的當前位置 74 int next[255]; //next數組 75 Get_Next(T, next); //調用Get_Next函數,為next賦值 76 int count = 0; 77 // printf("KMP算法中j回溯的值為:"); 78 while(i < Slength && j < Tlength) 79 { 80 // printf("%d ", j); 81 // count++; 82 if(j == -1 || S[i] == T[j]) //如果j==-1,說明前綴已經回退到最前方 83 { //如果S[i] == T[j],說明主串與子串當前位置字符相等 84 i++; //S的當前位置後移一位 85 j++; //T的當前位置後移一位 86 } 87 else 88 { 89 j = next[j]; //否則,j回退(未弄懂回退到哪) 90 } 91 } 92 // printf("\nj共變化了%d次\n", count); 93 if(j == Tlength) //比較結束,判斷j的值是否與T的長度相等 94 return i - Tlength; //若是,返回T在S中出現的開始位置 95 else 96 return -1; //若不是,返回-1 97 } 98 99 /*KMP改進版算法*/ 100 void Get_Next_Val(char *T, int nextVal[]) 101 { 102 int Tlength = StringLength(T); //獲得子串T的長度 103 int i = 0; //記錄後綴位置 104 int j = -1; //記錄前綴位置 105 nextVal[0] = -1; //next數組第一位置賦值為-1 106 while(i < Tlength) 107 { 108 if(j == -1 || T[i] == T[j]) //同上 109 { 110 i++; //同上 111 j++; 112 if(T[i] != T[j]) //如果位置後移一位後的值不相等 113 nextVal[i] = j; //nextVal等於j 114 else //如果相等 115 nextVal[i] = nextVal[j]; //當前後綴位置的nextVal值等於j位置的nextVal的值 116 } 117 else 118 j = nextVal[j]; //同上 119 } 120 } 121 122 int Index_KMP_Val(char *S, char *T) 123 { 124 int Slength = StringLength(S); //獲得主串S的長度 125 int Tlength = StringLength(T); //獲得子串T的長度 126 int i = 0; //記錄S的當前位置 127 int j = 0; //記錄T的當前位置 128 int next[255]; //next數組 129 Get_Next_Val(T, next); //調用Get_Next函數,為next賦值 130 int count = 0; 131 printf("KMP_Val算法中j回溯的值為:"); 132 while(i < Slength && j < Tlength) 133 { 134 printf("%d ", j); 135 count++; 136 if(j == -1 || S[i] == T[j]) //如果j==-1,說明前綴已經回退到最前方 137 { //如果S[i] == T[j],說明主串與子串當前位置字符相等 138 i++; //S的當前位置後移一位 139 j++; //T的當前位置後移一位 140 } 141 else 142 { 143 j = next[j]; //否則,j回退(未弄懂回退到哪) 144 } 145 } 146 printf("\nj共變化了%d次\n", count); 147 if(j == Tlength) //比較結束,判斷j的值是否與T的長度相等 148 return i - Tlength; //若是,返回T在S中出現的開始位置 149 else 150 return -1; //若不是,返回-1 151 } 152 153 154 155 void main() 156 { 157 char *S = "aaaaaaaaaaaaaaaaaaaaabcde"; 158 char *T = "aaaaaaaaaaaaaaaaaaaaaaaax"; 159 int pos; 160 pos = Index(S, T); 161 if(pos != -1) 162 printf("樸素匹配算法:子串T在主串S的下標為%d的位置上開始出現\n", pos); 163 else 164 printf("樸素匹配算法:子串T不存在與主串S中\n"); 165 printf("---------------------------------------------------------------------\n"); 166 int pos_KMP; 167 pos_KMP = Index_KMP(S, T); 168 if(pos_KMP != -1) 169 printf("KMP匹配算法:子串T在主串S的下標為%d的位置上開始出現\n", pos_KMP); 170 else 171 printf("KMP匹配算法:子串T不存在與主串S中\n"); 172 printf("---------------------------------------------------------------------\n"); 173 int pos_KMP_val; 174 pos_KMP_val = Index_KMP_Val(S, T); 175 if(pos_KMP_val != -1) 176 printf("KMP_Val匹配算法:子串T在主串S的下標為%d的位置上開始出現\n", pos_KMP_val); 177 else 178 printf("KMP_Val匹配算法:子串T不存在與主串S中\n"); 179 }
串的匹配算法--C語言實現