一.串的定义
1. 串是由零个或多个字符串组成的有限序列,又叫字符串;
2. 一般记为:s=“a1a2a3…an”(n>=0)。
其中s为串的名称,双引号中的字符序列为串值,ai[1,n],i是该字符在串中的位置,n为串长
3. 其他概念
(1)空格串:只包含空格的串。区别于空串,它是有长度的,而且可以有多个空格
(2)子串与主串:串中任意个数的连续字符组成的子序列称为该主串的子串
二.串的比较
1. 串的比较通过组成串的字符之间的编码来进行的,而字符的编码指该字符对应字符集的序号
2. 比较两个串是否相等,要比较其长度和对应位编码号是否相等。
3. 不相等字符串比较大小:
两个字符串,如果一个串是另一个字符串的子串,则子串小于主串;如果从第i位开始不相等,则比较第i位的编码值,编码值大的串大。
实例应用:英语词典
三.串的存储结构
1. 顺序存储结构
用一组地址连续的存储单元来存储字符序列,一般用定长数组来定义
2.链式存储结构
(1)与线性表相似,但每个节点存放1/多个字符。
对于单节点多字符,最后一个节点若未被占满则用默认值补全,所以节点存储字符长度影响着串处理效率,需要根据实际情况做出选择。
(2)性能评价:串的链式存储结构除了在连接串与串操作时方便外,总体性能不如顺序存储好
四.字符串匹配算法
0.将一字符串与目标字符串比较,看其是否是目标串的子串,并确定匹配位置
1. 普通/暴力匹配算法
从第一位开始匹配,出错后子串整体后移一位,效率极低
2.KMP算法
(1)实现步骤:
- 求前缀子串
- 取不等于本身的最长相等前后缀值
- 得出前缀表
- 两串进行比较,出现错误时,将子串出错位处【前缀值对应的序列号】移动到目标串出错位处,并向后继续比较
(2)代码:
public class StringKmp {
/**
* 用于计算匹配的位置(从头到尾)
*
* @param str
* @param sub
* @return
*/
public static int kmp(String str, String sub) {
if (str == null || sub == null || str.length() == 0 || sub.length() == 0) {
throw new IllegalArgumentException("str或者sub不能为空");
}
int j = 0;
int[] n = next(sub);
for (int i = 0; i < str.length(); i++) {
while (j > 0 && str.charAt(i) != sub.charAt(j)) {
j = n[j - 1];
}
if (str.charAt(i) == sub.charAt(j)) {
j++;
}
if (sub.length() == j) {
int index = i - j + 1;
return index;
}
}
return -1;
}
/**
* 用于生成部分匹配表
*
* @param sub
* @return
*/
private static int[] next(String sub) {
int[] n = new int[sub.length()];
int x = 0;
for (int i = 1; i < sub.length(); i++) {
while (x > 0 && sub.charAt(x) != sub.charAt(x)) {
x = n[x - 1];
}
if (sub.charAt(i) == sub.charAt(x)) {
x++;
}
n[i] = x;
}
return n;
}
public static void main(String[] args) {
String str = "BBCABCDABABCDABCDABDE";
String sub = "ABCDAB";
int index = StringKmp.kmp(str, sub);
System.out.println("index-->" + index);
}
}