暴力匹配算法
- int Violentmatch(char* s, char* p)
- {
- int sLen = strlen(s);
- int pLen = strlen(p);
- int ans = -1;
- int i = 0;
- int j = 0;
- while (i < sLen && j < pLen)
- {
- if (s[i] == p[j])
- {
- //①如果当前字符匹配成功(即S[i] == P[j]),则i++,j++
- i++;
- j++;
- }
- else
- {
- //②如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0
- i = i - j + 1;
- j = 0;
- }
- }
- if (j == pLen)
- {
- //匹配成功,返回模式串p在文本串s中的位置
- ans = i - j;
- }
- return ans;
- }
KMP算法
- 现在文本串S匹配到 i 位置,模式串P匹配到 j 位置
- 如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
- 如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j],模式串P相对于文本串S向右移动了至少1位(换言之,当匹配失败时,模式串向右移动的位数为:失配字符所在位置 - 失配字符对应的next 值,即移动的实际位数为:j - next[j],且此值大于等于1)
- int KMP(char* s, char* p, int n)
- {
- int ans = -1;
- int i = 0;
- int j = 0;
- int pLen = strlen(p);
- while (i < n)
- {
- //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
- if (j == -1 || s[i] == p[j])
- {
- i++;
- j++;
- }
- else
- {
- //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
- //next[j]即为j所对应的next值
- j = next[j];
- }
- if (j == pLen)
- {
- ans = i - j;
- break;
- }
- }
- return ans;
- }
如果给定的模式串是:“ABCDABD”,从左至右遍历整个模式串,其各个子串的前缀后缀分别如下表格所示:
也就是说,原字符串对应的各个前缀后缀的公共元素的最大长度表为(下简称《最大长度表》):
把next 数组跟之前求得的最大长度表对比后,不难发现,next 数组相当于“最大长度值” 整体向右移动一位,然后初始值赋为-1。意识到了这一点,你会惊呼原来next 数组的求解竟然如此简单!
换言之,对于给定的模式串:ABCDABD,它的最大长度表及next 数组分别如下:
根据最大长度表求出了next 数组后,从而有
失配时,模式串向右移动的位数为:失配字符所在位置 - 失配字符对应的next 值
求next 数组的代码如下所示:
- void getNext(char* p,int next[])
- {
- int pLen = strlen(p);
- next[0] = -1;
- int k = -1;
- int j = 0;
- while (j < pLen - 1)
- {
- //p[k]表示前缀,p[j]表示后缀
- if (k == -1 || p[j] == p[k])
- {
- ++j;
- ++k;
- next[j] = k;
- }
- else
- {
- k = next[k];
- }
- }
- }
感谢july大神
时间: 2024-09-20 12:33:18