第四章 串

@第四章 串

  • 结构体定义、 串的基本操作 、模式匹配算法

一、结构体定义

//定长顺序存储表示结构体定义
typedef struct 
{
    char str[maxSize+1]; //maxSize为已经定义的常量表示串的最大长度
    int length;
}Str;
//变长分配存储表示(又叫动态分配存储方法)
typedef struct
{
    char *ch;   // 指向动态分配存储区首地址的字符指针
    int length; //串长度
}Str;

二、串的基本操作
赋值操作、取串长度操作、串比较操作、串连接操作、求子串、串清空

//串的基本操作
//赋值操作,将一个常量字符串赋给str,操作成功返回1,否则返回0
int strassign(Str& str,char *ch)
{
    if(str.ch)
        free(str.ch);   //释放原串空间
    int len=0;
    char *c=ch;
    while(*c)           //求ch串的长度
    {
        ++len;
        ++c;
    }
    if(len==0)  //如果ch为空串,则直接返回空串
    {
        str.ch=NULL;
        str.length=0;
        return 1;
    }
    else
    {
        str.ch=(char*)malloc(sizeof(char)*(len+1));
        //去len+1是为了多分配一个空间存放“\0”字符
        if(str.ch==NULL)
            return 0;
        else
        {
            c=ch;
            for(int i=0;i<=len;++i,++c)
                str.ch[i]=*c;
            str.length=len;
            return 1;
        }
    }
}
//取串长度操作
int strlength(Str str)
{
    return str.length;
}
//串比较操作
int strcompare(Str s1,Str s2)
{
    for(int i=0;i<s1.length&&i<s2.length;++i)
        if(s1.ch[i]!=s2.ch[i])
            return s1.ch[i]-s2.ch[i];
    return s1.length-s2.length;
}
//串连接操作,将两个串首尾相连,合并成一个字符串
int concat(Str &str,Str str1,Str str2)
{
    if(str.ch)
    {
        free(str.ch);//
        str.ch=NULL;
    }
    str.ch=(char*)malloc(sizeof(char)*(str1.length+str2.length+1));
    if(str.ch==NULL)
        return 0;
    int i=0;
    while(i<str1.length)
    {
        str.ch[i]=str1.ch[i];
        ++i;
    }
    int j=0;
    while(j<=str2.length)
    //"<="
    {
        str.ch[i+j]=str.ch[j];
        ++j;
    }
    str.length=str1.length+str2.length;
    return 1;
}
//求子串 从给定串中某一位置开始到某一位置结束
//在str串中从pos位置开始,长度为len的子串,子串由substr返回
int substring(Str & substr,Str str,int pos,int len)
{
    if(pos<0||pos>=str.length||len<0||str.length-pos)
        return 0;
    if(substr.ch)
    {
        free(substr.ch);
        substr.ch=NULL;
    }
    if(len==0)
    {
        substr.ch=NULL;
        substr.length=0;
        return 1;
    }
    else
    {
        substr.ch=(char*)malloc(sizeof(char)*len+1);
        int i=pos;
        int j=0;
        while(i<pos+len)
        {
            substr.ch[j]=str.ch[i];
            ++i;
            ++j;
        }
        substr.ch[j]='\0';
        substr.length=len;
        return 1;
    }
}
//串清空操作
int clearstring(Str &str)
{
    if(str.ch)
    {
        free(str.ch);
        str.ch=NULL;
    }
    str.length=0;
    return 1;
}

三、模式匹配算法
BF算法和KMP算法
KMP算法原理参考链接:
https://blog.csdn.net/v_JULY_v/article/details/7041827
https://www.zhihu.com/question/34623343/answer/352148154
https://blog.csdn.net/buppt/article/details/78531384

BF算法
//串的模式匹配算法 BF算法
//若匹配成功,则返回模式串在主串中的位置,
//若不成功,则返回一个区别于主串所有位置的标记,如“0”
int index(Str str, Str substr)
{
    int i=1,j=1,k=i;
    while(i<=str.length&&j<=substr.length)
    {
        if(str.ch[i]==substr.ch[j])
        {
            ++i;
            ++j;
        }
        else
        {
            j=1;
            i=++k; //匹配失败,i从主串的下一个位置开始,k中记录了上一次的其实位置
        }        
    }
    if(j>substr.length)
        return k;
    else return 0;
}
KMP算法
//KMP算法
void getnext(Str substr,int next[])
{   //求模式串 substr 的next值并存入数组next
    int i=1,j=0;
    next[1]=0; //substr的第一个字符和主串失配时,主串的下一个字符与substr的第一个字符比较
    while(i<substr.length) //当substr.length>1时,next[2]=1
    {
        if(j==0||substr.ch[i]==substr.ch[j]) //初态或两字符相等
        {
            ++i; //各加1继续向后比较
            ++j;
            next[i]=j;
            //主串和substr在第i个字符不匹配时,前j-1个是匹配的,只需与第j个字符比较
        }
        else    //两字符不等
            j=next[j];  //j减小到前面字符相等之处
    }
}
int KMP(Str str,Str substr,int next[])
{
    int i=1,j=1;
    while(i<=str.length && j<=substr.length)
    {
        if(j==0||str.ch[i]==substr.ch[j])
        {
            ++i;
            ++j;
        }
        else //模式串向右移动
            j=next[j];
    }
    if(j>substr.length)  //匹配成功
        return i-substr.length;
    else
        return 0;
}

void GetNext(char * p, int next[])
{
	next[0] = -1;
	int i = 0, j = -1;

	while (i < strlen(p)-1)  //注意减1
	{
		if (j == -1 || p[i] == p[j]) //p[i]表示后缀,p[j]表示前缀
		{
			++i;
			++j;
			next[i] = j;
		}	
		else
			j = next[j];
	}
}

int KMPSearch(char * t, char * p) 
{
	int i = 0; 
	int j = 0;

	while (i < strlen(t) && j < strlen(p))
	{ //如果j=-1或者当前字符匹配成功,都令i++,j++
		if (j == -1 || t[i] == p[j]) 
		{
			i++;
           	j++;
		}
	 	else 
         {  //如果j!=-1,且当前字符匹配失败,则令i不变
            //next[j]为即为j所对应的next值
            j = next[j];
         }
           		
    }

    if (j == strlen(p))
       return i - j;
    else 
       return -1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值