• 模式串匹配、KMP算法及其改进(代码)


    1. #include "string.h"
    2. #include "stdio.h"
    3. #include "stdlib.h"
    4. #include "io.h"
    5. #include "math.h"
    6. #include "time.h"
    7. #define OK 1
    8. #define ERROR 0
    9. #define TRUE 1
    10. #define FALSE 0
    11. #define MAXSIZE 100 /* 存储空间初始分配量 */
    12. typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    13. typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
    14. typedef char String[MAXSIZE + 1]; /* 0号单元存放串的长度 */
    15. /* 生成一个其值等于chars的串T */
    16. Status StrAssign(String T, char *chars)
    17. {
    18. int i;
    19. if (strlen(chars)>MAXSIZE)
    20. return ERROR;
    21. else
    22. {
    23. T[0] = strlen(chars);
    24. for (i = 1; i <= T[0]; i++)
    25. T[i] = *(chars + i - 1);
    26. return OK;
    27. }
    28. }
    29. Status ClearString(String S)
    30. {
    31. S[0] = 0;/* 令串长为零 */
    32. return OK;
    33. }
    34. /* 输出字符串T。 */
    35. void StrPrint(String T)
    36. {
    37. int i;
    38. for (i = 1; i <= T[0]; i++)
    39. printf("%c", T[i]);
    40. printf(" ");
    41. }
    42. /* 输出Next数组值。 */
    43. void NextPrint(int next[], int length)
    44. {
    45. int i;
    46. for (i = 1; i <= length; i++)
    47. printf("%d", next[i]);
    48. printf(" ");
    49. }
    50. /* 返回串的元素个数 */
    51. int StrLength(String S)
    52. {
    53. return S[0];
    54. }
    55. /* 朴素的模式匹配法 */
    56. int Index(String S, String T, int pos)
    57. {
    58. int i = pos; /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    59. int j = 1; /* j用于子串T中当前位置下标值 */
    60. while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
    61. {
    62. if (S[i] == T[j]) /* 两字母相等则继续 */
    63. {
    64. ++i;
    65. ++j;
    66. }
    67. else /* 指针后退重新开始匹配 */
    68. {
    69. i = i - j + 2; /* i退回到上次匹配首位的下一位 */
    70. j = 1; /* j退回到子串T的首位 */
    71. }
    72. }
    73. if (j > T[0])
    74. return i - T[0];
    75. else
    76. return 0;
    77. }
    78. /* 通过计算返回子串T的next数组。 */
    79. void get_next(String T, int *next)
    80. {
    81. int i, j;
    82. i = 1;
    83. j = 0;
    84. next[1] = 0;
    85. while (i<T[0]) /* 此处T[0]表示串T的长度 */
    86. {
    87. if (j == 0 || T[i] == T[j]) /* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
    88. {
    89. ++i;
    90. ++j;
    91. next[i] = j;
    92. }
    93. else
    94. j = next[j]; /* 若字符不相同,则j值回溯 */
    95. }
    96. }
    97. /* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
    98. /* T非空,1≤pos≤StrLength(S)。 */
    99. int Index_KMP(String S, String T, int pos)
    100. {
    101. int i = pos; /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    102. int j = 1; /* j用于子串T中当前位置下标值 */
    103. int next[255]; /* 定义一next数组 */
    104. get_next(T, next); /* 对串T作分析,得到next数组 */
    105. while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
    106. {
    107. if (j == 0 || S[i] == T[j]) /* 两字母相等则继续,与朴素算法增加了j=0判断 */
    108. {
    109. ++i;
    110. ++j;
    111. }
    112. else /* 指针后退重新开始匹配 */
    113. j = next[j];/* j退回合适的位置,i值不变 */
    114. }
    115. if (j > T[0])
    116. return i - T[0];
    117. else
    118. return 0;
    119. }
    120. /* 求模式串T的next函数修正值并存入数组nextval */
    121. void get_nextval(String T, int *nextval)
    122. {
    123. int i, j;
    124. i = 1;
    125. j = 0;
    126. nextval[1] = 0;
    127. while (i<T[0]) /* 此处T[0]表示串T的长度 */
    128. {
    129. if (j == 0 || T[i] == T[j]) /* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
    130. {
    131. ++i;
    132. ++j;
    133. if (T[i] != T[j]) /* 若当前字符与前缀字符不同 */
    134. nextval[i] = j; /* 则当前的j为nextval在i位置的值 */
    135. else
    136. nextval[i] = nextval[j]; /* 如果与前缀字符相同,则将前缀字符的 */
    137. /* nextval值赋值给nextval在i位置的值 */
    138. }
    139. else
    140. j = nextval[j]; /* 若字符不相同,则j值回溯 */
    141. }
    142. }
    143. int Index_KMP1(String S, String T, int pos)
    144. {
    145. int i = pos; /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    146. int j = 1; /* j用于子串T中当前位置下标值 */
    147. int next[255]; /* 定义一next数组 */
    148. get_nextval(T, next); /* 对串T作分析,得到next数组 */
    149. while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
    150. {
    151. if (j == 0 || S[i] == T[j]) /* 两字母相等则继续,与朴素算法增加了j=0判断 */
    152. {
    153. ++i;
    154. ++j;
    155. }
    156. else /* 指针后退重新开始匹配 */
    157. j = next[j];/* j退回合适的位置,i值不变 */
    158. }
    159. if (j > T[0])
    160. return i - T[0];
    161. else
    162. return 0;
    163. }
    164. int main()
    165. {
    166. int i, *p;
    167. String s1, s2;
    168. StrAssign(s1, "abcdex");
    169. printf("子串为: ");
    170. StrPrint(s1);
    171. i = StrLength(s1);
    172. p = (int*)malloc((i + 1)*sizeof(int));
    173. get_next(s1, p);
    174. printf("Next为: ");
    175. NextPrint(p, StrLength(s1));
    176. printf(" ");
    177. StrAssign(s1, "abcabx");
    178. printf("子串为: ");
    179. StrPrint(s1);
    180. i = StrLength(s1);
    181. p = (int*)malloc((i + 1)*sizeof(int));
    182. get_next(s1, p);
    183. printf("Next为: ");
    184. NextPrint(p, StrLength(s1));
    185. printf(" ");
    186. StrAssign(s1, "ababaaaba");
    187. printf("子串为: ");
    188. StrPrint(s1);
    189. i = StrLength(s1);
    190. p = (int*)malloc((i + 1)*sizeof(int));
    191. get_next(s1, p);
    192. printf("Next为: ");
    193. NextPrint(p, StrLength(s1));
    194. printf(" ");
    195. StrAssign(s1, "aaaaaaaab");
    196. printf("子串为: ");
    197. StrPrint(s1);
    198. i = StrLength(s1);
    199. p = (int*)malloc((i + 1)*sizeof(int));
    200. get_next(s1, p);
    201. printf("Next为: ");
    202. NextPrint(p, StrLength(s1));
    203. printf(" ");
    204. StrAssign(s1, "ababaaaba");
    205. printf(" 子串为: ");
    206. StrPrint(s1);
    207. i = StrLength(s1);
    208. p = (int*)malloc((i + 1)*sizeof(int));
    209. get_next(s1, p);
    210. printf(" Next为: ");
    211. NextPrint(p, StrLength(s1));
    212. get_nextval(s1, p);
    213. printf("NextVal为: ");
    214. NextPrint(p, StrLength(s1));
    215. printf(" ");
    216. StrAssign(s1, "aaaaaaaab");
    217. printf(" 子串为: ");
    218. StrPrint(s1);
    219. i = StrLength(s1);
    220. p = (int*)malloc((i + 1)*sizeof(int));
    221. get_next(s1, p);
    222. printf(" Next为: ");
    223. NextPrint(p, StrLength(s1));
    224. get_nextval(s1, p);
    225. printf("NextVal为: ");
    226. NextPrint(p, StrLength(s1));
    227. printf(" ");
    228. StrAssign(s1, "00000000000000000000000000000000000000000000000001");
    229. printf("主串为: ");
    230. StrPrint(s1);
    231. StrAssign(s2, "0000000001");
    232. printf("子串为: ");
    233. StrPrint(s2);
    234. printf(" ");
    235. printf("主串和子串在第%d个字符处首次匹配(朴素模式匹配算法) ", Index(s1, s2, 1));
    236. printf("主串和子串在第%d个字符处首次匹配(KMP算法) ", Index_KMP(s1, s2, 1));
    237. printf("主串和子串在第%d个字符处首次匹配(KMP改良算法) ", Index_KMP1(s1, s2, 1));
    238. return 0;
    239. }





  • 相关阅读:
    vim复制
    嵌入式Linux学习(二)
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1025 数的划分
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
  • 原文地址:https://www.cnblogs.com/zhuzhenfeng/p/4626662.html
Copyright © 2020-2023  润新知