#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 255 //静态数组最大容量;若用ch[0]记录串长,1个字节范围0~255,即字符串长度不能超过255
#include <iostream>
using namespace std;
//串,字串string,即字符组成的有限序列,是特殊的线性表,串一般只存储字符
//子串:串中任意连续字符组成的子序列;主串;字符编号从1开始,子串的位置以第一个字符的位置为准,1个空格=1字节(1B)=8比特(bit)
/*串(顺序存储)*/
typedef struct{
char ch[MAXLEN];
int length; //定长的顺序存储(静态数组),对于静态数组存放串,默认ch[0]放弃不用,从ch[1]开始储存字符串,另外单独用变量length记录字符串长度(不含ch[0])
}SString;
typedef struct{
char *ch;
int length;
}HString;
void InitStr(HString &S){
S.ch = (char *)malloc(sizeof(char)); //这片空间需要free,这片空间是动态的
S.length=0;
};
/*串(链式存储)*/
typedef struct StringNode{
char ch[4]; //每个结点存放四个字节,提高存储密度
struct StringNode *next; //存放指向下个结点的指针(1个指针占4个字节),存储密度低
}StringNode, *String;
/*基本操作*/
//求子串
bool SubString(SString &Sub, SString S, int pos, int len){
if(pos+len-1>S.length)
return false;
for(int i=pos; i<pos+len; i++)
Sub.ch[i-pos+1]=S.ch[i];
Sub.length=len;
return true;
}
//比较字符串操作
int StrCompare(SString S,SString T){ //当return值为正,S>T;return为0,S=T;return为负,S<T
for(int i=1;i<S.length&&i<T.length;i++){
if(S.ch[i]!=T.ch[i])
return S.ch[i]-T.ch[i];
}
return S.length=T.length; //扫描过的所有字符都相同,则长度长的串更大
}
//定位操作,若主串S中存在与T相同的子串,则返回子串第一次出现的位置,否则返回值为0;
int Index(SString S,SString T){
int n=S.length, m=T.length, i=1;
SString Sub; //用于暂存子串
while(i<n-m+1){
SubString(Sub,S,i,m);
if(StrCompare(Sub,T)!=0) ++i; //子串不等,位置往后移1位继续对比
else return i; //找到相等子串,返回其位置i
}
return 0; //while循环结束后仍然无输出,则S中没有与T相等的子串,返回0
}
//朴素模式匹配算法,指针i多次回溯,增加时间成本
int Index2(SString S,SString T){
int k=1,j=1,i=k;
while(i<=S.length&&j<=T.length){
if(S.ch[i]==T.ch[j]){
++i;
++j;
} else{
k++; //一旦有相同子串扫描到,循环中止
i=k;
j=1;
}
}
if(j>T.length) //只有在主串找到与模式串相等的子串,j才会>T.length
return k;
else
return 0;
}
//KMP算法~手算next数组;S主串,T模式串
//next数组指的是当模式串扫描到第j个发现与主串不匹配时,j指针跳到第next[j]个处重新扫描;
//手算规则是:寻找T的前缀子串=S的后缀子串,记这个子串为S,next[j]=S长度+1;注意前缀子串不含最后一个元素,后缀子串不含第一个元素
//next[1]=0, next[2]=1; j=1不匹配时,i++,j++,next[j]=0
//KMP算法(在子串仅能部分匹配时表现比朴素算法好,避免主串指针i回溯)
int Index_KMP(SString S,SString T,int next[]){
int i=1,j=1; //字符串从1开始储存元素(ch[0]为空)
while(i<=S.length&&j<=T.length){ //字符串长度不包括ch[0]的部分
if(j==0||S.ch[i]==T.ch[j]){
i++; j++;
}
else
j=next[j]; //模式串指针向右移动,避免回溯
}
if(j>T.length) //代表模式串已遍历对比,主串中有相同子串
return i-T.length;
else
return 0; //主串已遍历对比,没有匹配模式串的
}
//KMP算法的优化-->nextval数组,当字符串前面有相同的元素,从next[0]开始从左往右确定nextval[]的值
//nextval数组替代next数组,避免相同元素重复匹配
void nextVal(SString T,int next[]){
int nextval[T.length];
for(int j=2;j<=T.length;j++){
if(T.ch[next[j]]==T.ch[j])
nextval[j]=nextval[next[j]];
else
nextval[j]=next[j];
}
}
int main(){
return 0;
}
【数据结构笔记】串(顺+链)+朴素算法+KMP算法
最新推荐文章于 2024-08-08 17:05:23 发布