//文字列KMPアルゴリズムのパターンマッチングプロセスが図に示されているため、説明しません
。//このプログラムは移植性プログラムです。
// Linux / Mac os / Windowsでコンパイルして実行できます。
//欠点がある場合は、それを上げてください。ブロガーは最善を尽くして修正します。
//それがあなたにとって有用であるならば、それを好きにするか、他の人と共有してください。
//盗用および許可なく転載することは固く禁じられています。
//ソースコードはこちらです。刺激を受けたいと思います。
//KMP.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20
char *s_gets(char *st, int n);
int kmp(const char *s, const char *t, int pos);
void get_next(const char *t, int *next);
int main(int argc, char *argv[])
{
int n;
char str1[LEN];
char str2[LEN];
printf("本程序采用KMP模式匹配算法判断子串是否处于主串中\n");
printf("请输入主串(换行结束输入):\n");
while (s_gets(str1, LEN) && *str1 != '\0')
{
printf("请输入子串:\n");
if (s_gets(str2, LEN) && *str2 != '\0')
{
n = kmp(str1, str2, 0); //从起始字符开始匹配,可任意决定匹配位置;
if (n != -1)
{
printf("子串%s在主串%s中, 子串出现于主串第%d个位置\n", str2, str1, n);
}
else
{
printf("子串%s不在主串%s中\n", str2, str1);
}
printf("您可以再次输入2串字符串(或换行退出):\n");
}
}
printf("本程序完成!\n");
return 0;
}
char *s_gets(char *st, int n)
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n');
if (find)
{
*find = '\0';
}
else
{
while (getchar() != '\n')
continue;
}
}
return ret_val;
}
int kmp(const char *s, const char *t, int pos)
{
int i = pos;
int j = 0;
int slength = strlen(s); //获取主串长度;
int tlength = strlen(t); //获取字串长度;
int *next = (int *)malloc(sizeof(int) * tlength); //构造一个与模式串长度相等的next数组;
if (NULL == next)
{
fprintf(stderr, "动态内存分配失败!本程序退出!\n");
exit(EXIT_FAILURE);
}
get_next(t, next); //给next数组赋初值;
while (i < slength && j < tlength)
{
if (j == -1 || s[i] == t[j])
{
i++;
j++;
}
else
{
j = next[j]; //模式串向右滑动;
}
}
free(next); //KMP算法匹配完之后释放next数组的动态内存空间;
if (j >= tlength)
{
return i - tlength + 1;
}
else
{
return -1;
}
}
void get_next(const char *t, int *next)
{
int i = 0;
int j = -1;
int len = strlen(t);
next[0] = -1;
while (i < len - 1)
{
if (j == -1 || t[i] == t[j])
{
next[++i] = ++j; //next数组中的核心部分,讲解如图所示;
}
else
{
j = next[j]; //模式串中的字符部分匹配,再求出next数组的函数值;
}
}
return;
}
//improvement_kmp.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20
char *s_gets(char *st, int n);
int kmp(const char *s, const char *t, int pos);
void get_nextval(const char *t, int *nextval);
int main(int argc, char *argv[])
{
int n;
char str1[LEN];
char str2[LEN];
printf("本程序采用KMP模式匹配算法判断子串是否处于主串中\n");
printf("请输入主串(换行结束输入):\n");
while (s_gets(str1, LEN) && *str1 != '\0')
{
printf("请输入子串:\n");
if (s_gets(str2, LEN) && *str2 != '\0')
{
n = kmp(str1, str2, 0); //从起始字符开始匹配,可任意决定匹配位置;
if (n != -1)
{
printf("子串%s在主串%s中, 子串出现于主串第%d个位置\n", str2, str1, n);
}
else
{
printf("子串%s不在主串%s中\n", str2, str1);
}
printf("您可以再次输入2串字符串(或换行退出):\n");
}
}
printf("本程序完成!\n");
return 0;
}
char *s_gets(char *st, int n)
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n');
if (find)
{
*find = '\0';
}
else
{
while (getchar() != '\n')
continue;
}
}
return ret_val;
}
int kmp(const char *s, const char *t, int pos)
{
int i = pos;
int j = 0;
int slength = strlen(s); //获取主串长度;
int tlength = strlen(t); //获取字串长度;
int *nextval = (int *)malloc(sizeof(int) * tlength); //构造一个与模式串长度相等的nextval数组;
if (NULL == nextval)
{
fprintf(stderr, "动态内存分配失败!本程序退出!\n");
exit(EXIT_FAILURE);
}
get_nextval(t, nextval); //给nextval数组赋初值;
while (i < slength && j < tlength)
{
if (j == -1 || s[i] == t[j])
{
i++;
j++;
}
else
{
j = nextval[j]; //模式串向右滑动;
}
}
free(nextval); //KMP算法匹配完之后释放nextval数组的动态内存空间;
if (j >= tlength)
{
return i - tlength + 1;
}
else
{
return -1;
}
}
void get_nextval(const char *t, int *nextval)
{
int i = 0;
int j = -1;
int len = strlen(t);
nextval[0] = -1;
while (i < len - 1)
{
if (j == -1 || t[i] == t[j]) //nextval数组中的核心部分,讲解如图所示;
{
++i, ++j;
if (t[i] != t[j])
{
nextval[i] = j; //字符不相等时的情况;
}
else
{
nextval[i] = nextval[j]; //字符相等时的情况;
}
}
else
{
j = nextval[j]; //模式串中的字符部分匹配,再求出nextval数组的函数值;
}
}
return;
}
// ------------------------------------------------ ---------;
//virus_detection.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define N 4
bool kmp(const char *s, const char *t, int pos);
void get_nextval(const char *t, int *nextval);
void virus_detection(void);
int main(void)
{
printf("本程序使用KMP算法查看病毒感染情况(病毒DNA为环状DNA)\n");
virus_detection();
return 0;
}
bool kmp(const char *s, const char *t, int pos)
{
int i = pos;
int j = 0;
int slength = strlen(s); //获取主串长度;
int tlength = strlen(t); //获取字串长度;
int *nextval = (int *)malloc(sizeof(int) * tlength); //构造一个与模式串长度相等的nextval数组;
if (NULL == nextval)
{
fprintf(stderr, "动态内存分配失败!本程序退出!\n");
exit(EXIT_FAILURE);
}
get_nextval(t, nextval); //给nextval数组赋初值;
while (i < slength && j < tlength)
{
if (j == -1 || s[i] == t[j])
{
i++;
j++;
}
else
{
j = nextval[j]; //模式串向右滑动;
}
}
free(nextval); //KMP算法匹配完之后释放nextval数组的动态内存空间;
if (j == tlength)
{
return true;
}
else
{
return false;
}
}
void get_nextval(const char *t, int *nextval)
{
int i = 0;
int j = -1;
int len = strlen(t);
nextval[0] = -1;
while (i < len - 1)
{
if (j == -1 || t[i] == t[j])
{
++i, ++j;
if (t[i] != t[j])
{
nextval[i] = j;
}
else
{
nextval[i] = nextval[j];
}
}
else
{
j = nextval[j];
}
}
return;
}
void virus_detection(void)
{
int i;
bool flag;
const char *people[N] = {
"da", "fg", "xi", "baa"};
const char *virus[N] = {
"abcdabcd", "efef", "hihi", "aaabaaab"};
//↑病毒DNA为环状DNA故字符串要成环, 原字符串连续存储2次即可;
for (i = 0; i < N; i++)
{
printf("第%d个人的DNA序列是:%s\n", i + 1, people[i]);
printf("第%d个病毒的DNA序列是:%s\n", i + 1, virus[i]);
flag = kmp(virus[i], people[i], 0);
if (flag)
{
printf("第%d个人感染了病毒\n\n", i + 1);
}
else
{
printf("第%d个人未感染病毒\n\n", i + 1);
}
}
return;
}
// ------------------------------------------------ ---------;
// ------------------------------------------------ -2020年6月26日---------------------------------------------- ----------;