typedef struct {//静态存储
char ch[MAXLEN];
int len;
}SString;
ch赋值需要用strcpy
strcpy(st.ch, "linjunjie");
typedef struct {//动态存储
char* ch;//按串的长度分配存储区,ch指向串的基地址
int length;
}HString;
typedef struct StringNode {//一个结点一个字符(低密度)
char ch;
struct StringNode* next;
}StringNode, * String;
typedef struct StringNode{//一个结点多个字符(高密度)
char ch[4];
struct StringNode* next;
}StringNode ,*String;
bool SubString(SString &Sub,SString S,int pos,int len)//求子串。用sub返回串s的第pos个字符起长度为len的字串
bool SubString(SString &Sub,SString S,int pos,int len)//求子串。用sub返回串s的第pos个字符起长度为len的字串
{
if (pos + len - 1 > S.len)return 0;//字串越界返回0
for (int i = pos; i < pos + len; i++)
Sub.ch[i - pos + 1] = S.ch[i];
Sub.len = len;
return 1;
}
int StrCompare(SString S, SString T)//比较操作。若S>T 则返回值>0 若S=T则返回值=0 若S
//比较操作。若S>T 则返回值>0 若S=T则返回值=0 若S
int StrCompare(SString S, SString T)
{
for (int i = 1; i < S.len && i < T.len; i++)
{
if (S.ch[i] != T.ch[i])
return S.ch[i] - T.ch[i];
}
//扫描过的所有字符都相同 则长度长的串更大
return S.len - T.len;
}
定位操作
int Index(SString S, SString T)//定位操作。若主串S中存在与T值相同的子串,则返回它在主串s中第一次出现的位置;否则函数值为0.
//定位操作。若主串S中存在与T值相同的子串,则返回它在主串s中第一次出现的位置;否则函数值为0.
int Index(SString S, SString T)
{
int i = 1, n = S.len, m = T.len;
SString sub;//用于暂存字串
while (i <= n - m + 1)
{
SubString(sub, S, i, m);
if (StrCompare(sub, T) != 0)i++;
else return i;//返回子串在主串中的位置
}
return 0;//S中不存在与T相等的子串
}
//朴素模式匹配算法(字符串空出首元素)
让主串的所有子串与模式串依次匹配,匹配成功返回位置
int Index(SString S,SString T)
{
int k = 1;
int i = k, j = 1;
while (i <= S.len && j <= T.len)
{
if (S.ch[i] == T.ch[j])
{
i++;
j++;
}
else
{
k++;
i = k;
j = 1;
}
}
if (j > T.len)return k;
else return 0;
}
解决朴素模式匹配算法模式串指针回溯问题
思想:“利用已经部分匹配这个有效信息,保持i指针不回溯,通过修改j指针,让模式串尽量地移动到有效的位置。”
//KMP算法(字符串首元素为空)
int Index_KMP(SString S, SString T, int next[])
{
int i = 1, j = 1;
while (i <= S.len && j <= T.len)
{
if (j == 0 || S.ch[i] == T.ch[i])
{
i++;
j++;//继续比较后继字符
}
else
j = next[j];//模式串向右移
}
if (j > T.len)return i - T.len;//匹配成功
else return 0;
}
平均时间复杂度O(n+m) n为主串长度 m为模式串长度
串的前缀:包含第一个字符,且不包含最后一个字符的子串
串的后缀:包含最后一个字符,且不包含第一个字符的子串
当第j个字符匹配失败时,由前1~j-1个字符组成的串记为s,则:
next[j]= s的前缀与后缀最长重复数k+1
别的,next[1]=0 `
前后缀不匹配next值为1
//求模式串的next数组
void get_next(SString T, int next[])
{
int i = 1, j = 0;
next[1] = 0;
while (i < T.len)
{
if (j == 0 || T.ch[i] == T.ch[j])
{
i++;
j++;
//若pi=pj,则next[j+1]=next[j]+1
next[i] = j;
}
else
j = next[j];
}
}
时间复杂度O(m) (m为模式串的长度)
优化为nextval数组
从j = 2开始依次判断Pnext是否等于Pnext[j] 是的话将next [j]修正为next [next [j]]直至者不相等为止
//优化的nextval数组
void get_nextval(SString T,int nextval[])
{
int i = 1,j = 0;
nextval[1] = 0;
while (i < T.len)
{
if (j == 0 || T.ch[i] == T.ch[j])
{
i++;
j++;
if (T.ch[i] != T.ch[j])
nextval[i] = j;
else j = nextval[j];
}
}
}