一般记为:
s="a1a2.......an"(a>=0)
注意:其中s是串名,用双引号括起来的字符序列为串值,双引号本身不属于串的内容。ai(1<=i<=n)是一个任意字符,它称为串的元素,是构成串的基本单位,i是它在整个串中的序号;n为串的长度,表示串中所包含的字符个数。
给定两个串:s=”a1a2……an”,t=”b1b2……bm”,当满足以下条件之一时,s < t:
1.n < m,且ai=bi(i=1,2,……,n),其中n代表s字符串的长度,s代表t字符串的长度,前面字符串都相同,但是s字符串的长度比t字符串小也就说明s字符串小于t字符串
2.存在某个k≤min(m,n)这是k>1的时候,使得ai=bi(i=1,2,……,k-1),ak < bk,如果两个字符串从第一个字符就开始不相等也就是说a1 != b1的话就直接只比较a1和b1的大小
ADT 串(string)
Data
串中元素仅由一个字符组成,相邻元素具有前驱和后继关系。
Operation
StrAssign(T, *chars): 生成一个其值等于字符串常量chars的串T
StrCopy(T, S): 串S存在,由串S复制得串T
ClearString(S): 串S存在,将串清空。
StringEmpty(S): 若串S为空,返回true,否则返回false。
StrLength(S): 返回串S的元素个数,即串的长度。
StrCompare(S, T): 若S>T,返回值>0,若S=T,返回0,若S<T,返回值<0。
Concat(T, S1, S2): 用T返回由S1和S2联接而成的新串。
SubString(Sub, S, pos, len): 串S存在,1≤pos≤StrLength(S),
且0≤len≤StrLength(S)-pos+1,用Sub返
回串S的第pos个字符起长度为len的子串。
Index(S, T, pos): 串S和T存在,T是非空串,1≤pos≤StrLength(S)。
若主串S中存在和串T值相同的子串,则返回它在主串S中
第pos个字符之后第一次出现的位置,否则返回0。
Replace(S, T, V): 串S、T和V存在,T是非空串。用V替换主串S中出现的所有
注意:我们在C语言当中定义一个字符数组的时候我们需要多加一个长度,因为编译器会自动的帮我们添加一个’\0’,这样方便去确定其的字符串的长度。但这个’\0’不会计入串长。
注意:一个节点可以存储一个字符,也可以存放一个字符数组,但是由于字符串的特殊性,用链表存作为字符串的存储方式也不太实用,因此使用较少。
int Index(String S,String T,int pos) //定义了一个主串,子串,开始查找的位置
{
int i=pos; //主串的查找位置,从该位置以后开始查找是否有字串
int j=1; //此处不太理解 为啥其实位置是1,感觉应该是0开始的
while(i<=S[0]&&j<=T[0])
{
if(S[i]==T[j])//判断两个字符串是否相等
{
++i; //两个相等时自加1,当判断出字串时,j=T的长度+1
++j;
}
else{
i=i-j+2; //两个字符不相等时,i-j的相当于返回了当前字串开头的那个字母的前一个字符,然后加2,就相当于从主串的下一个字符作为字串开头
j=1; //这时被匹配的字串回到首位
}
}
if(j>T[0])
return i-T[0];
else
return 0;
}
但是如果你的主串中匹配时大量每次匹配到最后那一个字符发现不相等,然后重新匹配。。。。如此循环往复,就会浪费大量的时间,因此就有了KMP模式匹配算法。
KMP则当到j位置不匹配时,主串不动,匹配串先通过计算从当前位置的前缀子串和后缀子串的最大匹配串的长度, KMP算法的精髓就是在于求next的过程。
注意:1.在我的理解中,前缀后必须有字符,不能整个字符是前缀,同理,后缀前也必须有字符。
例如:如果串是"aaaa",前缀就是"aa",后缀也是"aa",不能是"aaa".
2.对于模式串 T,next[j] 代表了 T 的前 j 个字符组成的子串中,其前缀和后缀的最长公共串的长度+1。
代码如下:
void get_next(char T[], int *next)
{
int i,j;
i = 1;
j = 0;
next[1] = 0;
while(i < T[0]) //T[0]是子串T的长度
{
//T[i]表示后缀的单个字符
//T[j]表示前缀的单个字符
if( j==0 || T[i] == T[j])
{
++i;
++j;
next[i] = j;
}
else
{
j = next[j];
}
}
}
整体KMP代码如下:
int Index_KMP(char S[], char T[], int pos)
{
int i = pos;
int j = 1;
int next[255];
get_next(T, next);
while(i <= S[0] && j <= T[0]){
//相对于朴素算法,增加了一个j==0的判断
if( j==0 || S[i] == T[j]){
++i;
++j;
}else{
//j回退到合适的位置,i的值不变
j = next[j];
}
}
if( j>T[0]){
return i-T[0];
}else{
return 0;
}
}