一:返回模式串在主串的下标BF与KMP与KMP1
#include <iostream>
#include<malloc.h>
#include<cstdio>
using namespace std;
#define MaxSize 100
int next[MaxSize];
int nextval[MaxSize];
typedef struct
{
char data[MaxSize];
int length;
} SqString;
void Assign(SqString &s,char cstr[])
{
int i;
for(i=0; cstr[i]!='\0'; i++)
s.data[i]=cstr[i];
s.length=i;
}
int BF(SqString s,SqString t)
{
int i=0,j=0;
while(i<s.length&&j<t.length)
{
if(s.data[i]==t.data[j])
{
i++;
j++;
}
else
{
i=i-j+1;
j=0;
}
}
if(j>=t.length)
return i-t.length;
else
return -1;
}
void GetNext(SqString t,int next[])
{
int i=0,j=-1;
next[0]=-1;
while(i<t.length-1)
{
if(j==-1||t.data[i]==t.data[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int KMP(SqString s,SqString t)
{
int i=0,j=0;
GetNext(t,next);
while(i<s.length&&j<t.length)
{
if(j==-1||s.data[i]==t.data[j])
{
i++;
j++;
}
else
j=next[j];
}
if(j>=t.length)
return i-t.length;
else
return -1;
}
void GetNextVal(SqString t,int next[])
{
int i=0,j=-1;
nextval[0]=-1;
while(i<t.length)
{
if(j==-1||t.data[i]==t.data[j])
{
i++;
j++;
if(t.data[i]!=t.data[j])
nextval[i]=j;
else
nextval[i]=nextval[j];
}
else
j=nextval[j];
}
}
int KMP1(SqString s,SqString t)
{
int i=0,j=0;
GetNextVal(t,next);
while(i<s.length&&j<t.length)
{
if(j==-1||s.data[i]==t.data[j])
{
i++;
j++;
}
else
j=nextval[j];
}
if(j>=t.length)
return i-t.length;
else
return -1;
}
int main()
{
SqString s,t;
Assign(s,"abcdefghi");
Assign(t,"cdef");
printf("用BF算法返回匹配下标:");
printf("%d\n",BF(s,t));
printf("用KMP算法返回匹配下标:");
printf("%d\n",KMP(s,t));
printf("用修正后的KMP算法返回匹配下标:");
printf("%d\n",KMP1(s,t));
return 0;
}
二:返回模式串在主串中出现的次数
如图:
#include <iostream>
#include<malloc.h>
#include<cstdio>
using namespace std;
#define MaxSize 100
int next[MaxSize];
int nextval[MaxSize];
int n;
typedef struct
{
char data[MaxSize];
int length;
} SqString;
void Assign(SqString &s,char cstr[])
{
int i;
for(i=0; cstr[i]!='\0'; i++)
s.data[i]=cstr[i];
s.length=i;
}
int BF(SqString s,SqString t)
{
int i=0,j=0,n=0;
while(i<s.length&&j<t.length)
{
if(s.data[i]==t.data[j])
{
i++;
j++;
}
else
{
i=i-j+1;
j=0;
}
///仅仅在此部分做了处理
if(j>=t.length)
{
n++;
i=i-j+1;
j=0;
}
}
return n;
}
void GetNext(SqString t,int next[])
{
int i=0,j=-1;
next[0]=-1;
while(i<t.length-1)
{
if(j==-1||t.data[i]==t.data[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int KMP(SqString s,SqString t)
{
int i=0,j=0,n=0;
GetNext(t,next);
while(i<s.length&&j<t.length)
{
if(j==-1||s.data[i]==t.data[j])
{
i++;
j++;
}
else
j=next[j];
///仅仅在此部分做了处理
if(j>=t.length)
{
n++;
i=i-j+1;
j=0;
}
}
return n;
}
void GetNextVal(SqString t,int next[])
{
int i=0,j=-1;
nextval[0]=-1;
while(i<t.length)
{
if(j==-1||t.data[i]==t.data[j])
{
i++;
j++;
if(t.data[i]!=t.data[j])
nextval[i]=j;
else
nextval[i]=nextval[j];
}
else
j=nextval[j];
}
}
int KMP1(SqString s,SqString t)
{
int i=0,j=0,n=0;
GetNextVal(t,next);
while(i<s.length&&j<t.length)
{
if(j==-1||s.data[i]==t.data[j])
{
i++;
j++;
}
else
j=nextval[j];
///仅仅在此部分做了处理
if(j>=t.length)
{
n++;
i=i-j+1;
j=0;
}
}
return n;
}
int main()
{
SqString s,t;
Assign(s,"abcdefghicdefcdef");
Assign(t,"cdef");
printf("用BF算法返回匹配次数:");
printf("%d\n",BF(s,t));
printf("用KMP算法返回匹配次数:");
printf("%d\n",KMP(s,t));
printf("用修正后的KMP算法返回匹配次数:");
printf("%d\n",KMP1(s,t));
return 0;
}
三:最小循环节,即最大的循环次数
如图:POJ2406
len-next[len]是最小循环节,而len/(len-next[len])是最大的循环次数
#include <iostream>
#include<string.h>
#include<cstdio>
using namespace std;
char t[1000000];
int next[1000000];
void getnext()
{
int i=0,j=-1;
next[0]=-1;
while(i<strlen(t))
{
if(j==-1||t[i]==t[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
while(scanf("%s",t))
{
if(t[0]=='.')
break;
int len=strlen(t);
getnext();
if(len%(len-next[len])==0)
printf("%d\n",len/(len-next[len]));
else
printf("1\n");
}
return 0;
}
字符串的所有大小循环节以及他们的周期POJ1961
如图:
///i-next[i]是循环节的长度
void getnext(const char *t)///有无参数都行
#include <iostream>
#include<string.h>
#include<cstdio>
using namespace std;
char t[1000000];
int next[1000000];
int len;
void getnext(const char *t)///无参数也行
{
int i=0,j=-1;
next[0]=-1;
while(i<strlen(t))
{
if(j==-1||t[i]==t[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int ant=0;
while(scanf("%d",&len)&&len)
{
scanf("%s",t);
getnext(t);///无参数也行
printf("Test case #%d\n",++ant);
for(int i=1;i<=len;i++)
{
if(i%(i-next[i])==0&&(i!=i-next[i])) ///如果有多个循环节
printf("%d %d\n",i,i/(i-next[i]));
}
printf("\n");
}
return 0;
}
哈哈