串(String)是由零个或者多个字符组成的有序序列,又名叫字符串
空格串 :是只包含空格的串,注意它和空串的区别,空格串是有长度的,而且可以不止一个空格.
子串与主串,串中任意个数的连续字符组成的子序列称为该串的子串,相应地,包含子串的串称为主串
子串在主串的位置就是子串的第一个字符在主串中的序号
数组和链表都能存
不过实际来看链表弊端很明显,一个字符对应一个节点,就会存在很大的空间浪费,若是存放多个字符,又考虑多少个问题,这都会影响串处理的效率,但是在连接串与串操作方便
总的来说:顺序存储灵活,性能比链表存储结构好
BF (Brute Force) 的缩写,就是暴力算法,拆开字符一个个比较,通俗易懂,符合常理和第一反应,当然效率肯定慢啊,都暴力算法了.
截图君上场,简单介绍一下暴力算法,知道的可以直接忽略
这个时间复杂度算起来也挺有意思的,故单独敲敲文字过一遍,主要查找的时候有特殊情况,会影响到时间复杂度的计算
设:主串为m
,子串为n
,
abcdefg
和子串nabc
,查找的次数一轮就通过为3次,根据大O时间复杂度计算1(<—不知道点这个1脚注),即为O(n)
O(m+n)
,因为所有字符都要一个个匹配,在遍历m
的基础上,再加上n
000000000001
和001
,这种情况,每个字符都要匹配3
次,001
三个长度,直到匹配第三个1
的时候,才发现不是,所以时间复杂度是前面的匹配长度乘以后面的长度,这样一来时间复杂度O(n*(m-n+1))
,一般实际使用时m >> n,所以可以认为趋近于O(m*n)
package com.company;
/**
* @Author: comfort
* @Date: 2020/8/4
*/
public class StringTest {
public static void main(String[] args) {
String source = "abcdefghijklmn";
String look = "jkl";
System.out.println(BF(source, look));
}
/**
* BF暴力检索
* @param source 原字符串
* @param lookupStr 要查找的字符串
* @return 成功返回下标,否则-1
*/
public static int BF(String source,String lookupStr){
//初始化从0开始的下标
int souIndex=0;
int lookIndex=0;
//转化char根据字符一一查找
char[] sourceChar = source.toCharArray();
char[] lookChar = lookupStr.toCharArray();
//思路 :判断时,要已两个字符的下标长度为条件
while (souIndex<sourceChar.length&&lookIndex<lookChar.length ){
System.out.println(souIndex+" "+sourceChar[souIndex]+" "+lookIndex+" "+lookChar[lookIndex] );
//两个字母相等
if (sourceChar[souIndex] == lookChar[lookIndex]) {
souIndex++;
lookIndex++;
}else{
//找不到 回退
//如果当前字符匹配不成功,则souIndex回溯到此次匹配最开始的位置+1处,也就是
//souIndex = souIndex - lookIndex + 1
souIndex=souIndex-lookIndex+1;
lookIndex=0;
}
}
if (lookIndex == lookChar.length) {
return souIndex - lookIndex;
}
return -1;
}
}
0 a 0 j
1 b 0 j
2 c 0 j
3 d 0 j
4 e 0 j
5 f 0 j
6 g 0 j
7 h 0 j
8 i 0 j
9 j 0 j
10 k 1 k
11 l 2 l
9
当然,如果字符串不存在,一直会检索所有(13次)
比如我输入lmc
时,主串一直从头运行到最后,最后返回-1
0 a 0 l
1 b 0 l
2 c 0 l
3 d 0 l
4 e 0 l
5 f 0 l
6 g 0 l
7 h 0 l
8 i 0 l
9 j 0 l
10 k 0 l
11 l 0 l
12 m 1 m
13 n 2 c
12 m 0 l
13 n 0 l
-1
while
循环条件和初始化index
比较重要,书中写的是从1
开始,故重置算法是i=i-j+2
,看的我云里雾里,自己翻了资料,发现初始化index
从0
开始比较符合思路.i=i-j+1
这行代码比较直接给出来了,其实自己找个纸画画,目的就是j=0
时,让i
变回上一次开始的位置,多举两三个例子,就发现了i
和j
之间的关系.其他:这篇有点水文字了…本来想和KMP算法写在一起,发现kmp篇幅太长,在kmp算法的基础,还是分开写.酱紫吧.
参考资料:
字符串模式匹配算法系列(一):BF算法
推导大O阶:1.
用常数1取代运算时间中的所有加法常数 2.
在修改后的运行数次中,只保留最高阶.3.
如果最高阶项存在且不是1,则去除与这个项的常数 ↩︎