方法一:
很容易想到,也比较简单的方法就是遍历字符串,将每个字母作为起始字符判断是否匹配。
代码实现:
char str[100],target[100];
int t=1;
scanf("%s %s",str,target);
char*p1=str;
while(*p1)
{
char* p2=target;char* pstart=p1;
while(p1&&p2&&*p1==*p2)
{
p1++;
p2++;
}
if(!*p2)printf("%d\n",t);//也可以返回指针如果需要,这里是序号;
p1=pstart+1;t+=1;
}
方法二:
Rabin-Karp 算法
将每一个匹配子串映射为一个hash值。例如,将子串看做一个进制数,比较它的值与母串中相同长度子串的hash值,如果相同,再细致地按字符确认字符串是否确实相同。顺序计算母串hash值的过程中,使用增量计算的方法类似滑动窗口:扣除最高位的hash值,增加最低位的hash值。
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#define BASE 256
#define PRIME 101//数值可以不同且哈希函数不唯一,深入知识我也不是很明白 0.0 。
int hash(char *str, int len) {
int h = 0;
for (int i = 0; i < len; i++) {
h = (h * BASE + str[i]) % PRIME;
}
return h;
}
int RabinKarp(char *s, char *pattern) {
int n = strlen(s);
int m = strlen(pattern);
int hpattern = hash(pattern, m);
int hs = hash(s, m);
for (int i = 0; i <= n - m; i++) {
if (hs == hpattern) {
int j;
for (j = 0; j < m; j++) {
if (s[i + j] != pattern[j]) {
break;
}
}
if (j == m) {
return i+1;//返回数值为起始字母序号
}
}
hs = (hs - s[i] * (int)(pow(BASE, m - 1))) * BASE + s[i + m];
hs = (hs % PRIME + PRIME) % PRIME;
}
return -1;
}
int main() {
char str[100], target[100];
scanf("%s %s", str, target);
int index = RabinKarp(str, target);
if (index != -1) {
printf("Substring found at index: %d\n", index);
} else {
printf("Substring not found.\n");
}
return 0;
}