[关闭]
@WangYixu 2018-06-21T09:54:05.000000Z 字数 839 阅读 706

KMP

OI 算法 笔记 字符串

  1. //KMP
  2. //思想是通过预处理减小失配时的代价
  3. //例子:
  4. /*
  5. * s1 : aaaaba
  6. * s2 : aaba
  7. * KMP匹配过程
  8. * aaaaba
  9. * ^
  10. * a^
  11. * aa^
  12. * aa^ X
  13. * aa^
  14. * aab^
  15. * aaba !!!
  16. */
  17. #include<cstdio>
  18. #include<cstring>
  19. const int N = 1000000 + 5;
  20. char s1[N], s2[N];
  21. int len1, len2;
  22. int shift[N];
  23. //shift[j]表示当匹配到 s2 的第 j 个字母而第 j + 1个字母不能匹配了时,新的 j' 最大是多少
  24. int main() {
  25. scanf("%s\n%s", s1 + 1, s2 + 1);
  26. int i = 0, j = 0;
  27. len1 = strlen(s1 + 1); len2 = strlen(s2 + 1);
  28. /************再看这里************/
  29. /*求shift数组的过程类似于自己和自己匹配*/
  30. /*shift[j]保证了s2中[1 .. shift[j]] == [j - shift[j] + 1 .. j]*/
  31. shift[1] = 0;
  32. j = 0;
  33. for(i = 2; i <= len2; ++i) {
  34. while(j && s2[i] != s2[j+1])
  35. j = shift[j];
  36. if(s2[i] == s2[j+1]) {
  37. ++j;
  38. }
  39. shift[i] = j;
  40. }
  41. /************先看这里************/
  42. /*i是当前匹配到的位置,j是当前匹配的长度*/
  43. j = 0;
  44. for(i = 1; i <= len1; ++i) {
  45. while(j && s1[i] != s2[j+1])
  46. j = shift[j];/*如果失配,就移动*/
  47. if(s1[i] == s2[j+1])
  48. ++j;/*如果匹配,就增加j*/
  49. if(j == len2) {/*匹配结束*/
  50. printf("%d\n", i - len2 + 1);
  51. j = shift[j];
  52. }
  53. }
  54. /*现在关键就是如何求shift数组*/
  55. for(int i = 1; i <= len2; ++i) {
  56. printf("%d ", shift[i]);
  57. }
  58. return 0;
  59. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注