zoukankan      html  css  js  c++  java
  • kmp(看*)算法

    别人的两篇博客。

    传送门1

    传送门2

    摘录:

    其中T为主串,P为模式串。

    其实就是在T中找P。

    其中next数组存的是“部分匹配值”。

    "部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例,

    - "A"的前缀和后缀都为空集,共有元素的长度为0;

    - "AB"的前缀为[A],后缀为[B],共有元素的长度为0;

    - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

    - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

    - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;

    - "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;

    - "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

    "部分匹配"的实质是,有时候,字符串头部和尾部会有重复。比如,"ABCDAB"之中有两个"AB",那么它的"部分匹配值"就是2("AB"的长度)。搜索词移动的时候,第一个"AB"向后移动4位(字符串长度-部分匹配值),就可以来到第二个"AB"的位置。

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 int lenT, lenP;
     5 int next[1001];
     6 char T[1000001], P[1001];
     7 
     8 void make_next()
     9 {
    10     int i, k = 0;
    11     for(i = 1; i < lenP; i++)
    12     {
    13         while(k && P[i] != P[k]) k = next[k - 1];
    14         if(P[i] == P[k]) k++;
    15         next[i] = k;
    16     }
    17 }
    18 
    19 int kmp()
    20 {
    21     int i, k = 0;
    22     make_next();
    23     for(i = 0; i < lenT; i++)
    24     {
    25         while(k && P[k] != T[i]) k = next[k - 1];
    26         if(P[k] == T[i]) k++;
    27         if(k == lenP) printf("%d
    ", i - lenP + 2);
    28     }
    29 }
    30 
    31 int main()
    32 {
    33     int i;
    34     scanf("%s", T);
    35     scanf("%s", P);
    36     lenT = strlen(T);
    37     lenP = strlen(P);
    38     kmp();
    39     for(i = 0; i < lenP; i++) printf("%d ", next[i]);
    40     return 0;
    41 }
    View Code

    后话。。。。。。。。。。

    事实上,下标从1开始在某些问题上处理边界更好处理

    update

    #include <cstdio>
    #include <cstring>
    #define N 1000001
    
    int n, m;
    int next[N];
    char s1[N], s2[N];
    
    inline void make_next()
    {
    	int i, j = 0;
    	for(i = 2; i <= m; i++)
    	{
    		while(j && s2[i] != s2[j + 1]) j = next[j];
    		if(s2[i] == s2[j + 1]) j++;
    		next[i] = j;
    	}
    }
    
    inline void kmp()
    {
    	int i, j = 0;
    	for(i = 1; i <= n; i++)
    	{
    		while(j && s1[i] != s2[j + 1]) j = next[j];
    		if(s1[i] == s2[j + 1]) j++;
    		if(j == m) printf("%d
    ", i - m + 1);
    	}
    }
    
    int main()
    {
    	int i;
    	scanf("%s %s", s1 + 1, s2 + 1);
    	n = strlen(s1 + 1);
    	m = strlen(s2 + 1);
    	make_next();
    	kmp();
    	for(i = 1; i <= m; i++) printf("%d ", next[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    This counter can increment, decrement or skip ahead by an arbitrary amount
    LUT4/MUXF5/MUXF6 logic : Multiplexer 8:1
    synthesisable VHDL for a fixed ratio frequency divider
    Bucket Brigade FIFO SRL16E ( VHDL )
    srl16e fifo verilog
    DualPort Block RAM with Two Write Ports and Bytewide Write Enable in ReadFirst Mode
    Parametrilayze based on SRL16 shift register FIFO
    stm32 spi sdcard fatfs
    SPI bus master for System09 (2)
    SQLSERVER中的自旋锁
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6644544.html
Copyright © 2011-2022 走看看