您的位置:首页 > 其它

KMP算法的几种模板

2017-08-23 20:34 211 查看
一、寻找子串首次出现的位置

代码:

 C++ Code 
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

///寻找子串首次出现的位置
#include<stdio.h>
int a[1000010], b[10010];
int next[10010];
int n, m;
void getNext()

{

    ///求next数组
    ///j表示前缀(前缀是固定的),i表示后缀(后缀是相对的)
    int i, j;

    i = 0;

    j = -1;

    next[0] = -1;

    while(i < m)

    {

        if(j == -1 || b[i] == b[j]) ///如果可以匹配,都加一进行下一轮匹配
        {

            i++;

            j++;

            next[i] = j;

        }

        else j = next[j]; ///如果不能匹配,就退回到next[j];
    }

}
///返回首次出现的位置
int KMP_Index()

{

    int i = 0, j = 0;

    getNext();

    while(i < n && j < m)

    {

        if(j == -1 || a[i] == b[j])

        {

            i++;

            j++;

        }

        else j = next[j];

    }

    if(j == m)

        return i - m + 1;

    else

        return -1;

}
int main()

{

    int T;

    scanf("%d", &T);

    while(T--)

    {

        scanf("%d%d", &n, &m);

        for(int i = 0; i < n; i++)

            scanf("%d", &a[i]);

        for(int i = 0; i < m; i++)

            scanf("%d", &b[i]);

        
da73
printf("%d\n", KMP_Index());

    }

    return 0;

}

二、统计子串出现的个数

代码:

 C++ Code 
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

///统计子串出现的次数
#include<bits/stdc++.h>
using namespace std;
char W[10010], T[1000010];
int wlen, tlen;
int next[10010];
void getNext()

{

    int i, j;

    i = 0;

    j = -1;

    next[0] = -1;

    while(j < wlen)

    {

        if(j == -1 || W[i] == W[j])

        {

            i++;

            j++;

            next[i] = j;

        }

        else j = next[j];

    }

}
int KMP_count()

{

    int ans = 0;

    int i, j = 0;

    if(wlen == 1 && tlen == 1)

    {

        if(W[0] == T[0])

            return 1;

        else

            return 0;

    }

    getNext();

    for(i = 0; i < tlen; i++)

    {

        while(j > 0 && T[i] != W[j])

            j = next[j];

        if(W[j] == T[i])

            j++;

        if(j == wlen)

        {

            ans++;

            j = next[j];

        }

    }

    return ans;

}
int main()

{

    int tcase;

    scanf("%d", &tcase);

    while(tcase--)

    {

        scanf("%s%s", &W, &T);

        wlen = strlen(W);

        tlen = strlen(T);

        printf("%d\n", KMP_count());

    }

    return 0;

}

ps:kmp算法的核心就是避免不必要的回溯,那么什么是不必要的呢?问题由模式串决定,不是由目标串决定
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: