一、与串相关的概念
1、串(或字符串)是由零个或多个字符组成的有限序列。一般记作:s=〃c0c1c2…cn-1〃(n≥0)。零个字符的串称为空串,通常以两个相邻的双引号来表示空串,仅由空格组成的的串称为空格串,如:s=〃 〃;
2、串与线性表的异同。字符串一般简称为串,可以将它看作是一种特殊的线性表,这种线性表的数据元素的类型总是字符型的,字符串的数据对象约束为字符集。在线性表的基本操作中,大多以“单个元素”作为操作对象,而在串中,则是以“串的整体”或一部分作为操作对象。因此,线性表和串的操作有很大的不同。
3、当两个串的长度相等且各对应位置上的字符都相同时,这两个串是相等的。串中任意个连续字符组成的序列称为该串的子串。包含子串的串被称为主串。
4、模式匹配:子串定位运算称为模式匹配(Pattern Matching)或串匹配(String Matching)。模式匹配成功是指在目标串s中找到一个模式串t;模式匹配不成功则指目标串s中不存在模式串t。在串匹配中,一般将主串称为目标串,子串称之为模式串。
二、串的几种表示方法
1、顺序存储结构 (静态)
分配一组地址连续的存储单元存放串值的字符序列。
#define MAXSTRLEN 255
typedefunsigned char SString[MAXSTRLEN+1];
2、串的块链存储表示
块,一组连续的字符。块链存储表示,把串分成指定等长的块,每一块用一个结点表示,把各块链成一个链表。当一个结点不满时,用特殊字符(如‘#’)填充。若块的长度为1,就是以单字符为结点的链表结构。
#define CHUNKSIZE <结点的大小> ; //定义结点的大小
typedef struct Chunk { //结点结构
char str[CHUNKSIZE];
struct Chunk *next;
} Lstring;
块的大小与存储密度有关:
3、堆分配存储表示(常用)
堆存储结构的特点是,仍以一组空间足够大的、地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配的。所以也称为动态存储分配的顺序表。每当产生一个新串时,系统就从剩余空间的起始处为串值分配一个长度和串值长度相等的存储空间。
在C语言中,存在一个称为“堆”的自由空间,由动态分配函数malloc()分配一块实际串长所需的存储空间,如果分配成功,则返回这段空间的起始地址,作为串的基址。由free()释放串不再需要的空间。
C语言对堆分配存储结构的定义如下:
typedef struct{
char *str;
int curlen;
}Hstring;
三、Brute-Force算法的思想
Brute-Force算法的基本思想是:从目标串s 的第一个字符起和模式串t的第一个字符进行比较,若相等,则继续逐个比较后续字符,否则从串s 的第二个字符起再重新和串t进行比较。依此类推,直至串t 中的每个字符依次和串s的一个连续的字符序列相等,则称模式匹配成功,此时串t的第一个字符在串s 中的位置就是t 在s中的位置,否则模式匹配不成功。
四、Brute-Force算法的C语言描述
五、Brute-Force算法的C语言实现
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#define OK 1
#define ERROR 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int Boolean; // Boolean是布尔类型,其值是TRUE或false
#define N 16 // 数据元素个数
#define MAXKEYLEN 16 // 关键字的最大长度
#define STACK_INIT_SIZE 10 // 存储空间初始分配量
#define STACKINCREMENT 2 // 存储空间分配增量
typedef struct
{
char *ch;
int length;
}HString;
void InitString(HString &T)
{ // 初始化(产生空串)字符串T
T.length=0;
T.ch=NULL;
}//InitString
int StrAssign(HString&T,char *chars)
{// 生成一个其值等于串常量chars的串T
int i,j;
if(T.ch)
free(T.ch); //释放T原有空间
i=strlen(chars);//求chars的长度i
if(!i)
{//chars的长度为0
T.ch=NULL;
T.length=0;
}//if
else
{
T.ch=(char*)malloc(i*sizeof(char));//分配串空间
if(!T.ch) exit(-1); //失败
for(j=0;j
T.ch[j]=chars[j];
T.length=i;
}//else
return OK;
}//StrAssign
void StrPrint(HString &T)
{
int i;
for(i=0;i printf("%c",T.ch[i]); printf("\n"); }//StrPrint int Index(HString s,HStringt,int pos) { int i,j; i=pos; //指向串s的第1个字符 j=0; //指向串t的第1个字符 while((i if(s.ch[i]==t.ch[j]) //比较两个子串是否相等 { ++i; //继续比较后继字符 ++j; }//if else { i=i-j+1; //串s指针回溯重新开始寻找串t,注意,在算法中我们的存储结构是数组,我//们在此实现中,采用的是堆,导致语句有点小不一样。 j=0; }//else if(j>=t.length)return(i-t.length+1); //匹配成功,返回模式串t在串s中的起始位置 else return 0; //匹配失败返回0 } void OutprintS(HString &t) { printf("串t为: "); StrPrint(t); }//OutprintS void InputS(HString &s) { char ch[80]; printf("input theString:\n"); scanf("%s",ch); StrAssign(s,ch); }//InputS int main() { int i,pos=1; HString t,s; InitString(s);//由于HSring定义了指针,所以必须初始化 InitString(t); InputS(s); InputS(t); OutprintS(s); OutprintS(t); i=Index(s,t,pos); printf("the location is:%d\n",i); return 1; } 六、Brute-Force算法的复杂度分析 最好的情况:算法时间复杂度为:O(Strlen(T)); 最坏的情况:算法时间复杂度为:O(Strlen(S)×Strlen(T))。