GetNext的个人理解:
首先先说一下next串的定义吧:
在对于字符串t中每个字符t[j](0<=j<=len-1),存在一个整数k(k
开头的k个字符依次与t[j]的前面的k个字符相同。
#include"顺序串.cpp"//关于顺序串的基本操作,下边放有源代码
void GetNext(SqString t,int next[])//求字符串t的next数组
{
int j,k;
j=0;
k=-1;//j扫描t,k记录t[j]之前于t开头相同的字符个数
next[0]=-1;
while(j=t.len)
return (i-t.len);
else
return (-1);
}
int main()
{
char a1[]="aaaaaaxyzaaaa",a2[]="ababc";
SqString s1,s2;
StrAssign(s1,a1);
StrAssign(s2,a2);
//cout<
关于顺序串的基本操作。
#include
#include
#include
#define MaxSize 100
using namespace std;
typedef struct
{
char data[MaxSize];
int len;
} SqString;
void StrAssign(SqString &str,char cstr[])//将一个字符串常量赋给串str,即生成一个其值等于cstr的串s。
{
int i;
for (i=0; cstr[i]!='\0'; i++)
str.data[i]=cstr[i];
str.len=i;
}
void StrCopy(SqString &s,SqString t) //将串t复制给串s
{
int i;
for (i=0; istr*/
str.data[i]=s.data[i];
for (i=0; istr*/
str.data[s.len+i]=t.data[i];
return str;
}
SqString SubStr(SqString s,int i,int j)//返回串s中从第i(1≤i≤StrLength(s))个字符开始的、由连续j个字符组成的子串。
{
SqString str;
int k;
str.len=0;
if (i<=0 || i>s.len || j<0 || i+j-1>s.len)
{
printf("参数不正确\n");
return str; /*参数不正确时返回空串*/
}
for (k=i-1; kstr*/
str.data[k-i+1]=s.data[k];
str.len=j;
return str;
}
SqString InsStr(SqString s1,int i,SqString s2)//将串s2插入到串s1的第i个字符中,即将s2的第一个字符作为s1的第i个字符,并返回产生的新串
{
int j;
SqString str;
str.len=0;
if (i<=0 || i>s1.len+1) /*参数不正确时返回空串*/
{
printf("参数不正确\n");
return s1;
}
for (j=0; jstr*/
str.data[j]=s1.data[j];
for(j=0; jstr*/
str.data[i+j-1]=s2.data[j];
for (j=i-1; jstr*/
str.data[s2.len+j]=s1.data[j];
str.len=s1.len+s2.len;
return str;
}
SqString DelStr(SqString s,int i,int j)//从串s中删去第i(1≤i≤StrLength(s))个字符开始的长度为j的子串,并返回产生的新串。
{
int k;
SqString str;
str.len=0;
if (i<=0 || i>s.len || i+j>s.len+1)
{
printf("参数不正确\n");
return str; /*参数不正确时返回空串*/
}
for (k=0; kstr*/
str.data[k]=s.data[k];
for(k=i+j-1; kstr*/
str.data[k-j]=s.data[k];
str.len=s.len-j;
return str;
}
SqString RepStr(SqString s,int i,int j,SqString t)//在串s中,将第i(1≤i≤StrLength(s))个字符开始的j个字符构成的子串用串t替换,并返回产生的新串
{
int k;
SqString str;
str.len=0;
if (i<=0 || i>s.len || i+j-1>s.len)
/*参数不正确时返回空串*/
{
printf("参数不正确\n");
return str;
}
for (k=0; kstr*/
str.data[k]=s.data[k];
for (k=0; kstr*/
str.data[i+k-1]=t.data[k];
for(k=i+j-1; kstr*/
str.data[t.len+k-j]=s.data[k];
str.len=s.len-j+t.len;
return str;
}
void DispStr(SqString s)//输出串s的所有元素值
{
int i;
if (s.len>0)
{
for (i=0; i
KMP算法的优化nextval[]:
void GetNextval(SqString t,int nextval[])
{
int j=0,k=-1;
nextval[0]=-1;
while(j
书上代码的思路:
当找第j个字符时,考虑t[j]是否与t[next[j]]相等,(next数组中存储的是相同的字符的个数,同时这个数在数值上是与{相等字符个数后一个字符的下标}所相等的)
每一个t的next值都是与前一位的存储相关联,所以要与前一位的t[k]的字符进行比较。
if相等:
则j++,k++;
next[j]=k;
j++(因为next中位置的数据信息存储在j+1的位置上)
k++(因为比较字符相同,所以只需要在前者的k上+1即可)
else不相等:
K回退
找到0~k个字符“大串中”,找到已经匹配好的“小串”,若找到与t[j]相等的字符,
则把“当前”的k+1存入。若找不到,则此时的k一定回溯到了k=(-1);k++,j++;
此时t[j]的next为next[j+1]=-1+1=0;正好为0,没有相同的字符串。
由此也就解释了为何要将next[0]=-1。(可能有疑惑为什么小串的数值一定是匹配好的。::因为小串是在大串中的,而我们找的大串就是匹配好的大串,所以小串数值一定也是匹配好的)
(emmmm:当找不到相同的字符时,k=-1;k++,j++;k=0,正好符合0个字符与开头字符相同。存储在next[j+1]中,即next[j+1]=0为j的数据信息)
nextval优化的特点就是将失配的字符于此时next[]的值下的字符进行比较,若想等则直接递推,即nextval[j]=nextval[k];因为这两个字符串是相等的再与主串匹配时同样会失配。(当不相等时,则与next的赋值一样,另nextval[j]=k);例如A=C,C=C1,所以A=C1.所以相等时可直接跳过一次不必要的回溯,此优化是在next中进行的优化,优化结果为新的数组nextval[].
在这里我提供一种方便记忆的方法:1) t[j]!=t[k],nextval[j]=next[j];
2) t[j]==t[k],nextval[j]=nextval[k];
即:不相等,不变。相等,继承。
时间关系没有细写,我会再次完善本篇文章。