数据结构--串--字符串匹配算法

串的基本定义

串(String):零个或多个任意字符组成的有限序列

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWFVOfk1MRg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

几个术语

  • 子串:一个串中任意个连续字符组成的子序列(含空串)称为该串的子串

    • 例如 “abcde”的字串

      • “” 、“a”、“abc”、“abcd” 等

  • 真子串:是指不包含自身的所有子串。

  • 主串:包含子串的串相应地称为主串。

  • 字符位置:字符在序列中的序号为该字符在串中的位置 。

  • 子串位置:子串第一个字符在主串中的位置。

  • 空格串:由一个或者多个空格组成的串 与空串不同

  • 串相等:当且仅当两个串的长度相等并且各自对应位置上的字符都相等,这两个串才是相等的。

  • 所有的空串是相等的。 

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWFVOfk1MRg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

串的类型定义、存储结构及运算

  • StrAssign(&T, chars)

    • 初始条件:chars是字符串常址。

    • 操作结果:生成 一个其值等于chars的串T。

  • StrCopy(&T,S)

    • 初始条件:串s存在。

    • 操作结果:由串s复制得串T。

  • StrEmpty(S)

    • 初始条件:串s存在。

    • 操作结果:若s为空串,则返回 tr ue, 否则返回false。

  • StrCompar e(S,T)

    • 初始条件:串 s和T存在。

    • 操作结果:若S>T, 则返回值 >0; 若S=T, 则返回值= O; 若S

  • Replace(&S,T,V)

    • 初始条件:串S, T和V存在, T是非空串。

    • 操作结果:用V替换主串s中出现的所有与T相等的不重叠的子串。

  • Strlnsert(&S,pos,T)

    • 初始条件:串 s和 T 存在,1<=pos<=StrLength(S)+1。

    • 操作结果:在串 s 的第 pos 个字符之前插人串 。

  • StrDelete(&S,pos,len)

    • 初始条件:串 S 存在 ,1<=pos<=StrLength(S)-len+1

    • 操作结果:从串 s 中删除第 pos 个字符起长度为 len 的子串。

  • DestroyString (&S)

    • 初始条件:串s存在。

    • 操作结果:串s被销毁。

串中元素逻辑关系与线性表的相同,串可以采用与线性表相同的存储结构

 

串的存储结构

  • 串的顺序存储结构

# define MAXLEN 255
typedef struct{ 
    char ch[MAXLEN+1];      // 存储串的一维数组
    int length;             // 串的当前长度
}SString;
  • 串的链式存储结构

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWFVOfk1MRg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

# define CHUNKSIZE 80
typedef struct Chunk{
    char ch[CHUNKSIZE];
    struct Chunk *next;
}CHunk;

typedef struct{
    Chunk *head;		// 串的头指针
    int curlen;			// 串的当前长度
    Chunk *tail;		// 串的尾指针
}LString;

串的模式匹配算法

算法目的

确定主串中所含子串(模式串)第一次出现的位置(定位)

 

算法应用:

  • 搜索引擎、拼写检查、语言翻译、数据压缩

     

算法种类:

  • BF算法(Brute-Force,又称古典的、经典的、朴素的、穷举的)

  • KMP算法(特点:速度快)

 

BF算法

 

Brute-Force 简称BF算法,亦称简单匹配算法。采用穷举法的思路。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWFVOfk1MRg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

Index(S,T,pos)

  • 将主串的第pos个字符和模式串的第一个字符比较,

  • 若相等,继续逐个比较后续字符;

  • 若不等,从主串的下一字符起,重新与模式串的第一个字符比较

  • 直到主串的一个连续子串字符序列与模式串相等。返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功。

  • 否则,匹配失败,返回值0

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWFVOfk1MRg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

# include <stdio.h>
#include <string.h> 


# define MAXLEN 255
typedef struct{ 
    char ch[MAXLEN+1];		// 存储串的一维数组
    int length;				// 串的当前长度
}SString;

// BF算法
int Index_BF(SString S,SString T){
	int i = 1;
	int j = 1;
	while(i<=S.length&&j<=T.length){
		if(S.ch[i] == T.ch[j]){			// 主串和子串依次匹配下一个字符 
			++i;
			++j;
		}else{
			i = i-j+2;
			j = 1;		// 主串、子串指针回溯重新开始下一次匹配 
		} 
	}
	if(j>=T.length){
		return i-T.length;	// 返回匹配的第一个字符的下标 
	}else{
		return 0;			// 模式匹配不成功 
	}
} 

int main(){
	return 0;
}

 

KMP算法

算法思路:

KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-

Morria-Pratt 算法,简称 KMP 算法。该算法相对于 Brute-Force(暴力)算法有比较大的

改进,主要是消除了主串指针的回溯,从而使算法效率有了某种程度的提高。

 

利用已经部分匹配的结果而加快模式串的滑动速度

且主串S的指针i不必回溯,可提速到O(n+m)

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWFVOfk1MRg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

next函数改进

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWFVOfk1MRg==,size_20,color_FFFFFF,t_70,g_se,x_16

KMP算法的代码思路:

// KMP 算法
int Index_KMP(SString S,SString T,int pos){
    int i = pos;
    int j = 1;
    while( i<=S.length && j<=T.length){
        if( S.ch[i] == T.ch[j] || j == 0){
            i++;
            j++;
        }
        else{
            j = next[j];     /*i不变,j后退*/
        }
    }
    if(j>T.length){
        return i-T.length;
    }else{
        return 0;
    }
}

求 next[j] 的方法

// 求 next[j] 的方法
void get_next(SString T,int &next[]){
    int i = 1;
    int j = 0;
    next[1] = 0;
    while(i<=T.length){
        if(j==0|| T.ch[i] == T.ch[j]){
            i++;
            j++;
            next[i] = j;
        }else{
            j = next[j];
        }
    }
}

next 改进:

// next 改进
void get_nextval(SString T,int &nextval[]){
    int i = 1;
    int j = 0;
    nextval[1] = 0;
    while(i<T.length){
        if(T.ch[i] == T.ch[j]||j==0){
            i++;
            j++;
            if(T.ch[i] != T.ch[j]){
                nextval[i] = j;
            }
            else{
                nextval[i] = nextval[j]
            }
        }
        else{
            j = nextval[j];
        }
    }
} 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XUN~MLF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值