关于串的相关定义:
- 串:用‘ ’表示的字符序列
- 空串:包含零个字符的串
- 子串:包含传本身和空串的子串
- eg: 'abc'
- ('','a','b','c','ab','bc','ac','abc)
- 共7个:串的长度的阶乘+1(空串)
- 真子串:不包含自身的所有字串
- eg: 'abc'
- ('','a','b','c','ab','ac','bc')
- 共6个:串的长度的阶乘
- 空格串:一个或多个空格组成的串
串与字符串的比较:
串: | 字符串: |
用 ‘ ’ 单引号表示 | 用 "" 双引号表示 |
字符后直接‘ 结尾 | 字符串结尾默认“\0” |
串的长度为字符数 | 字符串长度为字符数+1(“\0”) |
空串: ‘’ | 空字符串: ”“ |
BF(朴素查找算法):
问题描述:
在主串str1 中查找子串str2 的位置,若主串中包含字串则返回主串中位置,否则返回-1;
查找引例:
- 主串:"ababcabcdabcde 子串:"abcd"
- 主串:"aaaaab" 子串:"aaaab"
思路引入:
在例1:主串依次遍历字串,当遇到与字串不匹配时,主串指针直接向后遍历,子串从头便利
例2:主串若如例1思路,主串指针不向后倒退,直接向后遍历则无法得到正确查找答案
BF算法思想:
从主串的pos 位置与字串的字符进行比较,相等时两个串的指针皆向后移动;
不等时:主串倒退到此次开始遍历子串的位置的下一位置,子串指针回到开头,重新开始比较;
具体实现:
int main()
{
const char *str1 = "ababcabcdabcdeabcdabcdd";
//主串
//const char* str1 = "abcd";
const char* str2 = "abcd";
//子串
int j =0;//pos位置
while(j!=-1)
{
j = BF(str1, str2, j);
printf("返回类比pos位置:%d\n", j);
if (j == -1)
break;
j += strlen(str2);
}
return 0;
}
int BF(const char* str1, const char* str2, int pos)
{
assert(str1 != NULL && str2 != NULL);
int len1 = strlen(str1);
int len2 = strlen(str2);
if (pos < 0||pos>=strlen(str1)||str1==NULL||str2==NULL)
return -1;
int i ; int j = 0;
i = pos;
while(i<len1&&j<len2)
{
if (str1[i] == str2[j])
{
i++;
j++;
}
else
{
i = i - j+1;
j = 0;
}
}
if (j == len2)
return i - j;
return -1;
}
函数功能:
- 判断参数是否有效;
- 计算两个字符串的长度(strlen()函数计算不包含"\0"的长度);
- 分别用 "i" "j" 代表两个字符串的指针下标
- 相等:++,向后遍历
- 不等: i 回到开始位置的下一位置,j 回到开头
- 当子串匹配且遍历完即代表查找成功
代码提示:
- 字符串比较只能用”strcmp()"函数,同时单个字符无法使用该函数比较,等号比较即可;
//判断相等:
//error:
strcmp(str1[i],str2[j])==0;
//right:
str1[i]==str2[j];
- %s :只能输出字符串,不能输出字符 eg:不能!str[i]
- %c:输出单个字符,无法输出字符串 eg:可以 str[i]
由结果输出可知:
该串从零号下标开始,第5,9,14,18位置均找到了子串
算法重点:
- 主串指针回退到开始遍历的下一位置
- 子串回退到开头
- 当子串遍历成功即代表查找成功
BF算法时间复杂度:
主串长度m,子串长度n;
最差情况:若主串中不包含子串时
主串遍历了最多(n)遍子串(m)
由此可得:O(m*n)