串、数组和广义表---一站式入门,数据结构其实很简单(串)

串(String):零个或多个任意字符组成的有限序列
·子串:串中任意个连续字符组成的子序列称为该串的子串
·主串:包含子串的串相应地称为主串
·字符位置:字符在序列中的序号为该字符在串中的位置
·子串位置:子串第一个字符在主串中的位置
·空格串:由一个或多个空格组成的串,与空串不同
·串相等:当且仅当两个串的长度相等并且各个对应位置上的字符都相同时,这两个串才是相等的。
所有的空串都是相等的
串的数据结构类型的定义
串的数据结构类型的定义
串的数据结构类型的定义串中元素逻辑关系与线性表相同,串可以采用和线性表相同的存储结构。
串的顺序存储结构
#define MAXLEN 255
typedef struct{
char ch[MAXLEN+1];//存储串的一维数组
int length;//串的当前长度长度
}SString;
串的链式存储结构
优点:操作方便;缺点:存储密度较低
优化:将多个字符放入一个节点内-------块链结构
#define CHUNKSIZE 80 //块的大小可由用户定义
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *head,*tail; //串的头指针和尾指针
int curlen; //串的当前长度
}LString; //字符串的块链结构

串的模式匹配算法
目的:确定母串中字串(模式串)第一次出现的位置
应用:搜索引擎,拼写检查,语言翻译,数据压缩
种类
1.BF算法(Brute-Force,又称古典的、经典的、朴素的、穷举的)
2.KMP算法(速度快)

lndex(S,T,pos)
将主串的第pos个字符和模式串的第一个字符比较,
若相等,继续逐个比较后续字符;
若不等,从主串的下一字符起,重新与模式串的第一个字符比较。
从起点开始
int Index_BF(SString S, SString T){
int i=1,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;//模式匹配不成功
}
从pos开始
int Index_BF(SString S, SString T,int pos){
int i=pos,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;//模式匹配不成功
}
算法复杂度O(m*n)

KMP算法<—KMP算法比较难懂,大家戳这里
A为主串,B为匹配串,m为匹配串长度

第一种:
for (int i=1;i<m;i++)
{
    next[0]=-1
    int j=next[i-1];
    while ((B[j+1]!=B[i])&&(j>=0))
        j=next[j];
    if (B[j+1]==B[i])
        next[i]=j+1;
    else
        next[i]=-1;
}
while (i<n)
{
    if (A[i]==B[j])
    {
        i++;
        j++;
        if (j==m)
        {
            printf("%d\n",i-m+1);//注意,这里输出的位置是从1开始标号的,如果你要输出从0开始标号的位置,应该是是i-m.
            j=next[j-1]+1;
        }
    }
    else
    {
        if (j==0)
            i++;
        else
            j=next[j-1]+1;
    }
}


第二种:
void get_ next(SString T, int &next[]){
i= 1; next[1] = 0;j = 0;
while( i<T.length){
if(j==0 || T.ch[i] == T.ch[j]){
++i; ++j;
next[i] = j;
}
else
j = next[j];
}
}
int Index_ KMP (SString S,SString T, int pos) {
i= pos,j =1;
while (i<S.length && j <T.length) {
if (j==0 || S.ch[i]==T.ch[j]){ i++;j++; }
else
j= next[j];/*i不变,j后退*/
}
if (j> T.length) return i-T.length; /*匹配成功*/
else
return 0;/*返回不匹配标志*/
}

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

第三种算法:
void getNext(char * p, int * next)
{
	next[0] = -1;
	int i = 0, j = -1;

	while (i < strlen(p))
	{
		if (j == -1 || p[i] == p[j])
		{
			++i;
			++j;
			next[i] = j;
		}	
		else
			j = next[j];
	}
}
int KMP(char * t, char * p) 
{
	int i = 0; 
	int j = 0;

	while (i < strlen(t) && j < strlen(p))
	{
		if (j == -1 || t[i] == p[j]) 
		{
			i++;
           		j++;
		}
	 	else 
           		j = next[j];
    	}

    if (j == strlen(p))
       return i - j;
    else 
       return -1;
}

作者:海纳
链接:https://www.zhihu.com/question/21923021/answer/281346746
来源:知乎

关于kmp算法有很多不同的表示方法

大家根据自己理解可以自由改动

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿***

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

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

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

打赏作者

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

抵扣说明:

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

余额充值