zoukankan      html  css  js  c++  java
  • 模式串匹配、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. }





  • 相关阅读:
    Windows下Rails2.0.2最简安装教程
    xmpp with openfire之三 openfire扩展小试 整合现有系统用户
    母亲的电话
    郁闷……
    博弈
    长春下雪了
    监考
    sql把逗号分隔的字符串拆成临时表
    SQL语句使用大全。
    Left Join、Right Join、Inner Join的区别
  • 原文地址:https://www.cnblogs.com/zhuzhenfeng/p/4626662.html
Copyright © 2011-2022 走看看