串
串(String)是由零个或多个任意字符组成的有限序列,又名字符串。
是一种特殊的内容受限的线性表
相关术语:
- 空格串:由一个或多个空格组成的串,与空串不同,空格串有内容有长度且只由空格组成
- 子串:串中任意个连续的字符组成的子序列(含空串)称为该串的子串
- 主串:包含子串的串就相应的称为主串
- 字符位置:字符在序列中的序号为该字符在串中的位置
- 子串位置:子串第一个字符在主串中的位置
- 串相等:当且仅当两个串长度相等,并且各个对应位置上的字符都相同时,这两个串才是相等的
所有的空串都相等 - 串的应用非常广泛,计算机的大多数非数值处理的对象大多数是字符串数据,例如:文字编辑、符号处理,各种信息系统等等
- 串中元素逻辑关系与线性表的相同,串可以采用与线性表相同的存储结构。
- 包括链式存储和顺序存储
串基本操作
- StrAssign(&T,chars)//串赋值
- StrCompare(S,T)//串比较
- StrLength(S)//求串长
- Concat(&T,S1,S2)//串连结
- SubString(&Sub,S,pos,len)//求子串
- StrCopy(&T,S)//串拷贝
- StrEmpty(S)//串判空
- ClearString (&S)//清空串
- Index(S,T,pos)//子串的位置
- Replace(&S,T,V)//串替换
- Strlnsert(&S,pos,T)//子串插入
- StrDelete(&S,pos,len)//子串删除
- DestroyString(&S)//串销毁
串的存储方式
串的顺序存储
1)静态数组,字符串有最大长度限制。
#define MAXSIZE 100//字符串的最大长度
typedef struct
{
char data[MAXSIZE];//用数组存储字符串中的元素
unsigned int length;//字符串中元素的个数
)String;
2)动态分配内存,字符串的长度可以自动护展。
typedef struct
{
char*data;
//存储字符串中元素的首地址。
unsigned int maxsize;//字符串的最大长度。
unsigned int length;//字符串的实际长度。
}String;
串的链式存储
typedef struct LNode
{
char data;//每个结点一个字符。
struct Lnode *next;
}LNode,*String;
//块串:实际不常用
#define NLENGTH 10
//每个结点的字符数。
typedef struct LNode{
char data[NLENGTH];//每个结点NLENGTH个字符。
struct Lnode*next;
}LNode,*String;
串的匹配算法
算法目的:确定主串中所含子串(模式串)第一次出现的位置(定位)
主串:
(模式串)子串:
BF算法
BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将主串SS的第一
个字符与模式串TT的第一个字符进行匹配,若相等,则继续比较SS的第二个字符和TT的第二个字
符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。
BF算法是一种蛮力算法。
KMP算法
KMP是BF优化,KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与目标串的匹配次数以达到快速匹配
目的。KMP算法的时间复杂度O(m+n),BF算法是O(mn)。
前缀:
后缀:
公共前后缀:
KMP算法的原理:
- 在匹配的过程中,目标串的指针不需要不回溯,只回溯模式串的指针;
- 如果模式串和目标串前n个字符匹配成功,遇到匹配失败的字符时,模式串的指针回溯的位置由模式串的内容决定(回溯到匹配失败位置前的模式串内容的最长公共前后缀的长度+1),然后继续比较。
KMP算法的核心是求next数组。
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
//函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define MAXSIZE 255
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
typedef struct String {
char* data;
int len;
} String;
Status StrAssign(String *S, char *data);
void printString(String* s);
void forceMatch(String* master, String* sub);
int* getNext(String* s);
void kmpMatch(String* master, String* sub, int* next);
#include "SeqString.h"
String* initString()
{
String* s = (String*)malloc(sizeof(String));
s->data = NULL;
s->len = 0;
return s;
}
Status StrAssign(String *S, char *data)
{
if (&S == NULL || data == NULL)
{
delete data;
return ERROR;
}
int len = 0;
char * temp = data;
while (*temp)
{
len++;
temp++;
}
if (len == 0)
{
S->data = NULL;
S->len = 0;
}
else
{
temp = data;
S->len = len;
S->data = (char *)malloc(sizeof(char) * (len + 1));
for (int i = 0; i < len; i++, temp++)
{
S->data[i] = *temp;
}
}
}
void printString(String* s)
{
for (int i = 0; i < s->len; i++) {
printf(i == 0 ? "%c " : "-> %c ", s->data[i]);
}
printf("\n");
}
void forceMatch(String* master, String* sub)
{
int i = 0;
int j = 0;
while (i < master->len && j < sub->len)
{
if (master->data[i] == sub->data[j])
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
}
if (j == sub->len)
{
printf("force match success.\n");
printf("子串在主串中的位置为%d\n", i - sub->len);
}
else
{
printf("force match fail.\n");
}
}
int* getNext(String* s)
{
int* next = (int*)malloc(sizeof(int) * s->len);
int i = 0;
int j = -1;
next[i] = j;
while (i < s->len - 1) {
if (j == -1 || s->data[i] == s->data[j]) {
i++;
j++;
next[i] = j;
}
else {
j = next[j];
}
}
return next;
}
void printNext(int* next, int len)
{
for (int i = 0; i < len; i++) {
printf(i == 0 ? "%d " : "-> %d ", next[i] + 1);
}
printf("\n");
}
void kmpMatch(String* master, String* sub, int* next)
{
int i = 0;
int j = 0;
while (i < master->len && j < sub->len) {
if (j == -1 || master->data[i] == sub->data[j]) {
i++;
j++;
}
else {
j = next[j];
}
}
if (j == sub->len) {
printf("kmp match success.\n");
printf("子串在主串中的位置为%d\n", i - sub->len);
}
else {
printf("kmp match fail.\n");
}
}
void test01()
{
String* s = initString();
String* s1 = initString();
StrAssign(s, "abaabbabc");
StrAssign(s1, "abc");
printString(s);
printString(s1);
forceMatch(s, s1);
}
void test02()
{
String* s = initString();
String* s1 = initString();
StrAssign(s, "abaabbabc");
StrAssign(s1, "abc");
printString(s);
printString(s1);
int* next = getNext(s1);
printNext(next, s1->len);
kmpMatch(s, s1, next);
}
int main() {
test02();
system("pause");
return 0;
}