- 实现功能: 从主串中第K个字符起,求出子串在主串中首次出现的位置,即模式匹配或串匹配。要求用三种模式匹配算法分别实现:
- 朴素的模式匹配算法(BF算法)
- KMP改进算法(Next[ ])
- KMP改进算法(NextVal[ ])
- 设计要求:
首先设计一个含有多个菜单项的主控菜单程序,然后再为这些菜单项配上相应的功能。
程序运行后,给出5个菜单项的内容和输入提示:
1.输入主串、子串和匹配起始位置
2.朴素的模式匹配算法
3.KMP改进算法(Next[ ])
4.KMP改进算法(NextVal[ ])
0.退出管理系统
请选择0—4:
菜单设计要求:使用数字0—4来选择菜单项,其它输入则不起作用。
输出结果要求:输出各趟匹配详细过程(其中3、4,首先输出Next[ ]或者NextVal[ ]的各元素的数值),然后输出匹配总趟数、单个字符比较次数、匹配成功时的位置序号或者匹配失败提示信息。
#include<stdio.h>
#include<string.h>
#define maxn 100000
/*
bacbababadababacamba
ababaca
aaabaaaab
aaaab
*/
/*
菜单二:输出各趟匹配的详细过程、匹配总趟数、单个字符比较次数、匹配成功时的位置序号或匹配失败提示信息
菜单三:输出next[]各元素数值、各趟匹配详细过程、匹配总趟数、单个字符比较次数、匹配成时的位置序号或匹配失败提示信息
菜单四:输出nextval[]各元素数值、各趟匹配详细过程、匹配总趟数、单个字符比较次数、匹配成时的位置序号或匹配失败提示信息
*/
char s[100],t[100],ss[maxn],tt[maxn]; //主串与模式串,ss与pp为了检验子串与主串的长度
int next[maxn],nextval[maxn],chcom[maxn]; //chcom数组记录字符比较次数
void print();
void Input();
void init(); //初始化各个数组
void BF();
void KMP(int y);
void get_next();
void get_nextval();
int jiancei();
int main(){
while(1){
char i[100];
print();
scanf("%s",&i[0]);
if(strlen(i)!=1||i[0]<'0'||i[0]>'4'){ //检验输入
printf("输入错误,请输入0-4中的数字\n");
continue;
}
if(i[0]=='1'){
Input();
}
else if(i[0]=='2'&&strlen(s)!=0&&strlen(t)!=0){
BF();
}
else if(i[0]=='3'&&strlen(s)!=0&&strlen(t)!=0){
get_next();
KMP(0);
}
else if(i[0]=='4'&&strlen(s)!=0&&strlen(t)!=0){
get_nextval();
KMP(1);
}
else if(i[0]=='0'){
printf("系统退出,感谢使用\n");
break;
}
else if(strlen(s)==0||strlen(t)==0){
printf("请先输入主串和模式串之后再进行匹配!\n");
}
else{
printf("输入错误,请输入0-4中的数字\n");
continue;
}
}
return 0;
}
void print(){
printf("**************************************************\n");
printf("* 1.输入主串、子串 *\n");
printf("* 2.朴素的模式匹配算法 *\n");
printf("* 3.KMP算法(Next[]) *\n");
printf("* 4.KMP改进算法(NextVal[]) *\n");
printf("* 0.退出管理系统 *\n");
printf("--------------------------------------------------\n");
printf(" 请输入你要选择的功能:\n");
}
void Input(){
printf("请输入主串:");
getchar();
scanf("%[^\n]",ss); // \n作为字符串输入的结束符,不能用%s,否则会把“ ”当作结束符
if(strlen(ss)>100){
printf("主串长度应不大于100,请重新输入!\n");
Input();
}
printf("请输入子串:");
scanf("%s",tt);
if(strlen(tt)>100){
printf("模式串长度应不大于100,请重新输入!\n");
Input();
}
int i;
for(i=0;ss[i]!='\0';i++){
s[i]=ss[i];
printf("%c",s[i]);
}
s[i]='\0';
printf("\n");
for(i=0;tt[i]!='\0';i++){
t[i]=tt[i];
printf("%c",t[i]);
}
t[i]='\0';
printf("\n");
int m=strlen(s);
int n=strlen(t);
if(m<n){
printf("主串长度应不小于模式串长度!请重新输入!\n");
Input();
}
}
void init(){ //初始化
for(int i=0;i<maxn;i++){
chcom[i]=0;
next[i]=0;
nextval[i]=0;
}
}
int jiancei(){
int n,ret=0;
int m=strlen(s);
do{
ret=scanf("%d",&n);
if(ret!=1){
printf("输入有误,请重新输入1-%d之间的数字\n",m);
fflush(stdin);
}
else if(n>m||n<1){
printf("输入有误,请重新输入1-%d之间的数字\n",m);
fflush(stdin);
}
}while(ret!=1||n>m||n<1);
//cout<<"输入的值为"<<n<<endl;
return n;
}
void BF(){
printf("----------------------------------------------------------------------------------------------\n");
init(); //初始化
int pos;
printf("请输入匹配的起始位置\n");
pos=jiancei();
int i=pos,j=1;
int m=strlen(s);
int n=strlen(t);
printf("----------------------------------------------------------------------------------------------\n");
while(i<=m && j<=n){
chcom[i-1]++;
if(s[i-1]==t[j-1]){
printf("主串第 %d 项与模式串第 %d 项匹配成功\n",i,j);
i++;
j++;
}
else {
printf("主串第 %d 项与模式串第 %d 项匹配失败,从主串第 %d 项、模式串第%d项开始匹配\n",i,j,i-j+2,1);
i=i-j+2;
j=1;
}
}
printf("----------------------------------------------------------------------------------------------\n");
if(j>n){
printf("字符串匹配成功,匹配总趟数为%d,位置序号为%d\n",i-n,i-n);
printf("----------------------------------------------------------------------------------------------\n");
for(int x=0;x<m;x++){
printf("第%d项比较次数为%d\n",x+1,chcom[x]);
}
}
else{
printf("匹配失败\n");
}
printf("----------------------------------------------------------------------------------------------\n");
}
void get_next(){
init();
int i=1;
next[1]=0;
int j=0;
int n=strlen(t);
while(i<n){
if(j==0 || t[i-1]==t[j-1]){
i++;
j++;
next[i]=j;
}
else{
j=next[j];
}
}
printf("----------------------------------------------------------------------------------------------\n");
for(int x=0;x<n;x++){
printf("next[ %d ]= %d \n",x+1,next[x+1]);
}
}
void get_nextval(){
init();
int i=1;
nextval[1]=0;
int j=0;
int n=strlen(t);
while(i<n){
if(j==0 || t[i-1]==t[j-1]){
i++;
j++;
if(t[i-1]!=t[j-1]){
nextval[i]=j;
}
else{
nextval[i]=nextval[j];
}
}
else{
j=nextval[j];
}
}
printf("----------------------------------------------------------------------------------------------\n");
for(int x=0;x<n;x++){
printf("nextval[ %d ]= %d \n",x+1,nextval[x+1]);
}
}
void KMP(int y){
printf("----------------------------------------------------------------------------------------------\n");
init(); //初始化
int pos;
printf("请输入匹配的起始位置\n");
pos=jiancei();
int i=pos,j=1;
int m=strlen(s);
int n=strlen(t);
int r=0; //总匹配趟数
printf("----------------------------------------------------------------------------------------------\n");
while(i<=m && j<=n){
chcom[i-1]++;
if(j==0 || s[i-1]==t[j-1]){
if(j!=0){
printf("主串第 %d 项与模式串第 %d 项匹配成功\n",i,j);
}
i++;
j++;
}
else{
r++;
if(y==0){
if(next[j]==0){
printf("主串第 %d 项与模式串第 %d 项匹配失败,从主串第 %d 项、模式串第1项开始匹配\n",i,j,i+1);
}
else{
printf("主串第 %d 项与模式串第 %d 项匹配失败,从主串第 %d 项、模式串第%d项开始匹配\n",i,j,i,next[j]);
}
j=next[j];
}
if(y==1){
if(nextval[j]==0){
printf("主串第 %d 项与模式串第 %d 项匹配失败,从主串第 %d 项、模式串第1项开始匹配\n",i,j,i+1);
}
else{
printf("主串第 %d 项与模式串第 %d 项匹配失败,从主串第 %d 项、模式串第%d项开始匹配\n",i,j,i,nextval[j]);
}
j=nextval[j];
}
}
}
printf("----------------------------------------------------------------------------------------------\n");
if(j>n){
printf("字符串匹配成功,匹配总趟数为%d,位置序号为%d\n",r+1,i-n);
printf("----------------------------------------------------------------------------------------------\n");
for(int x=0;x<m;x++){
printf("第%d项比较次数为%d\n",x+1,chcom[x]);
}
}
else{
printf("匹配失败\n");
}
printf("----------------------------------------------------------------------------------------------\n");
}