题目
有主串 S="abcacabdc",模式串T="abd",请找出模式串在主串中第一次出现的位置。提示:主串和模式串均为小写字母且都是合法输入。
示例1
输入: S = "abcacabdc",T = "abd"
输出: 5
BF算法
思路
- 遍历主串,若主串的字符 等于 模式串的第一个字符,开始之后的是否与模式串相等,记录相等字符个数
range。 - 若
range等于模式串长度,则跳出循环,返回第一个字符索引 - 若
range不等于模式串长度,则直接将遍历索引i+ range - 1进行跳跃遍历。
复杂度
时间复杂度:
空间复杂度:
代码实现
int indexAt(char *s,char *subs){
int i = 0;
int result = -1;
while(s[i] != '\0'){
if (s[i] == subs[0])
{
int index = i;
index++;
int range = 1;
while(subs[index - i] != '\0' && s[index] == subs[index - i]){
printf("%c\n", subs[index - i]);
range++;
index++;
}
if (range == strlen(subs))
{
result = i;
break;
}else{
i = i+range - 1;
}
}
i++;
}
return result;
}
Sunday算法
思路
- 若主串的字符等于模式串的第一个字符,开始之后的是否与模式串相等,记录相等字符个数
range。 - 若
range等于模式串长度,则跳出循环,返回第一个字符索引 - 若
range不等于模式串长度,判断i + TLen是否小于主串长度,若小于则判断(i + TLen)处的字符串是否出现在模式串中(从右到左比较),若出现 则(i = i + 所在模式串中的位置)。若未出现,则i = (i+ TLen). - 继续迭代
复杂度
时间复杂度:
空间复杂度:
代码实现
int strStr(char * S, char * T){
int SLen = strlen(S);
int TLen = strlen(T);
if( SLen < TLen) {
return -1;
}
if(T == 0){
return 0;
}
int result = -1;
int i = 0;
while(i < SLen){
if (S[i] == T[0])
{
int temp = 1;
while(temp < TLen){
if (S[i + temp] == T[temp])
{
temp++;
}else{
break;
}
}
if (temp == TLen)
{
result = i;
break;
}
}
int temp = TLen - 1;
if (i + TLen < SLen)
{
while(temp > 0){
if (S[i + TLen] == T[temp])
{
break;
}
temp--;
}
i = (TLen- temp ) + i;
}else{
break;
}
}
return result;
}
KMP算法
介绍
KMP 算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个 next() 函数实现,函数本身包含了模式串的局部匹配信息。
例:模式串T ABABAA,在已经匹配的模式串子串中,找出最长的相同的前缀和后缀的字符个数记录在 Next 数组相应位置。
| 模式串T | A | B | A | B | A | A |
|---|---|---|---|---|---|---|
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 |
| Next数组 | 0 | 0 | 1 | 2 | 3 | 1 |
步骤
-
求导
Next数组- 声明两个变量索引
k与 临时记录相同前缀与后缀字符个数j,next[0] = 0; k在 内做递增循环。当T[j] != T[k]并且j > 0时,j = next[j - 1],直到j = 0 || T[j] = T[k]循环截止;- 当
T[j] = T[k]时,j++; next[k] = j。
- 声明两个变量索引
-
根据
Next数组信息,进行主串与模式串的匹配。- 声明两个变量
i与j,分别记录主串S访问索引与模式串T访问索引; i在 内递增循环。当j > 0并且S[i]!=T[j]时 ,j = next[j - 1],直到j = 0||S[i] = T[j]循环截止;- 当
S[i] = T[j]时,j++; - 若
j = TLen, 已匹配到对应字符串,否则返回-1。
- 声明两个变量
复杂度
时间复杂度:
空间复杂度:
代码实现
int *getKMPNext(char *T) {
int Tlen = strlen(T);
int *next = (int *)malloc(sizeof(int) * Tlen);
next[0] = 0;
int temp = 0;
for (int k = 1; k < Tlen; k++) {
while (temp > 0 && T[temp] != T[k]) {
temp = next[temp - 1];
}
if (T[temp] == T[k]) {
temp++;
}
next[k] = temp;
}
return next;
}
int strStr(char *S, char *T) {
int SLen = strlen(S);
int TLen = strlen(T);
if (TLen == 0) {
return 0;
}
int *next = getKMPNext(T);
for (int i = 0, j = 0; i < SLen; i++) {
while (j > 0 && S[i] != T[j]) {
j = next[j - 1];
}
if (S[i] == T[j])
j++;
if (j == TLen)
return i - j + 1;
}
return -1;
}