|||
串的模式匹配---------KMP
----曹星
一.思考sizeof,比较sizeof与strlen的区别?
二.注意char的特性
整形数与ASC码值的转换:
#include<stdio.h>
int main( )
{
int a=56;
printf("%c\n",(char)a);
return 0;
}
思考:我怎么样用一个字符数组来实现记录字符串的长度又实现对字符串的存储?
#include<stdio.h>
int main( )
{
char s[100];
char ch;
int i=1;
while((ch=getchar( ))!='\n') //依次读入字符
{
s=ch; //字符数组存储字符
i++;
}
s[0]=i-1; //存储字符串长度
printf("%d\n",s[0]); //打印字符数组长度
for(i=1;i<=s[0];i++)
{
printf("%c",s); //打印字符数组
}
printf("\n");
return 0;
}
切记:不能用以下方法,为什么?在什么条件下可以?
……
s[0]=‘i-1’; //存储字符串长度
……
for(i=1;i<=s[0]-'0';i++)
{
printf("%c",s); //打印字符数组
}
……
思维的开拓创新:我怎么用gets函数来实现一个字符数组既能记录字符串的长度又能对字 符串的存储
#include<stdio.h>
#include<string.h>
int main( )
{
char s[100];
char *P;
P=&s[1];
gets(P);
s[0]=strlen(P);
printf("%d\n",s[0]);
printf("%s\n",P);
for(int i=1;i<=s[0];i++)
{
printf("%c",s);
}
printf("\n");
return 0;
}
三.KMP原理讲解及附录本人编写的KMP代码
1>原理基本构造:
由定义知next[1]=0;
设next[j]=k,这表明在模式串中存在下列关系:
‘P1…Pk-1’ = ‘Pj-k+1…Pj-1’ 1》
其中k为满足1<k<j的某个值,并且不可能存在k'>k满足等式1》,此时next[j+1]=?
可能有两种情况:
(1) 若Pk=Pj,则表明在模式串中
‘P1…Pk’ = ‘Pj-k+1…Pj’ 2》
并且不可能存在k'>k满足等式2》,这就是说next[j+1]=k+1,即
next[j+1]=next[j] + 1 3》
思考一下为什么?
(2)若Pk≠Pj,则表明在模式串中
‘P1…Pk’≠ ‘Pj-k+1…Pj’
此时可把next函数值的问题看成是一个模式匹配的问题,整个模式串即是主串又是 模式串,而当前在匹配的过程中已有Pj-k+1=P1,Pj-k+2=P2,…,Pj-1=Pk-1,则当
Pj≠Pk时应将模式向右滑动到模式中的第next[k]个字符和主串中的第j个字符相比
较。若next[k]=k',且Pj=Pk',则说明在主串中第j+1个字符之前存在一个长度为为
K'(即next[k])的最后子串,和模式中从首字符起长度为k'的子串相等,
‘P1…Pk'’= ‘Pj-k'+1…Pj’(1<k'<k<j) 4》
这就是说 next[j+1]=k'+1
` 即next[j+1]=next[k]+1;
同理若Pj≠Pk'则将模式继续向右滑动直至将模式中第next[k']个字符和Pj对齐,……
依次类推,直至Pj和模式中某个字符匹配成功,或者不存在任何k'(1<k'<j)满足4》
则
next[j+1]=1;
2>KMP源代码 :
/*串的模式匹配算法*/
// 文件:cpp1.cpp
// 程序员:caoxing
// 日期:2011-3-24
// 概要:处理字符串的匹配问题
// 组成:由两个自定义函数和一个主函数:
// get_nextval(char T[ ],int nextval[ ]);
// Index_KMP(char T[ ],char S[ ],int pos,int nextval[ ]);
// main( );
// 目的:为文本编辑程序和建立词索引表程序做基础
#include<stdio.h>
#include<string.h>
void get_nextval(char T[ ],int nextval[ ])
{//求模式串T的next函数修正值并存入数组nextval.
int i=1,j=0;
nextval[1]=0;
int length;
length=strlen(T);
while(i<length)
{
if(j==0||T==T[j])
{
++i;
++j;
if(T==T[j])
nextval=nextval[j];
else
nextval=j;
}
else
j=nextval[j];
}
}
int Index_KMP(char S[ ],char T[ ],int pos,int nextval[ ])
{//利用模式串T的nextval函数求S在主串T的第pos个字符之后的位置的
//KMP算法。其中,S非空,1<=pos<=lengthT;
int i=pos;
int j=1;
while(i<=S[0]&&j<=T[0])
{
if( j==0 || S==T[j] )
{
++i;
++j; //继续比较后继字符
}
else
j=nextval[j]; //模式串向后移动
}
if(j>T[0])
return (i-T[0]);//匹配成功
else
return 0;
}
int main( )
{
char S[256],T[256];
char *P,*Q;
int nextval[256];
int pos; //指定在主串S中开始比较的位置
while(1)
{
P=&S[1];
Q=&T[1];
gets(P);
gets(Q); //输入两个字符串
S[0]=strlen(P);
T[0]=strlen(Q); //得到两个字符串的长度
scanf("%d",&pos);
get_nextval(T,nextval);
printf("%d\n",Index_KMP(S,T,pos,nextval));
getchar( );
}
return 0;
}