1字符串暴力匹配
具体原理不过多解释。
代码如下:
#include<stdio.h>
#include<stdlib.h>
typedef struct String{
char* data;//C里面没有字符串的概念,所以需要字符型指针来代替这个而且最后一个是\0结尾.
int len;
}String;
//初始化
String* initString(){
String* S=(String*)malloc(sizeof(String));
S->data=NULL;
S->len=0;
return S;
}
//data的数据需要一个输入函数,因此需要写一个输入函数
void stringAssign(String*s,char* data){
if(s->data){
free(s->data);
}
int len=0;//字符串有多长
char * temp=data;//找一个变量代替data
while(*temp){//data
len++;
temp++;//数组的第一个元素,顺序表的直接加一,不需要考虑指针
}
s->len=len;
//上面得到data的长度len,temp指向最后一个data[len-1];
if(len == 0){//为空
s->data=NULL;
//s->len=0;
}
else{
//有值
// s->len=len;
temp=data;
//开辟空间的理解还是不够
s->data=(char*)malloc(sizeof(char)*(len+1));//多一个存\0
//为什么要开辟空间呢?因为我要输入一个值,那么我希望得到一些内存空间。
for(int i=0;i<len;i++,temp++){
s->data[i]=*temp;//学习这种表示方式,*temp=data[i];
}
}
}
//输出字符串
void printString(String* s){
for(int i=0;i< (s->len);i++){
printf(i==0 ? "%c":"->%c",s->data[i]);//注意i==0!!
}
printf("\n");
}
//完成暴力匹配算法
void forceMatch(String* master,String* sub){
//定义两个指针
int i=0;
int j=0;//这样跟int i,j=0;有区别吗???
//int a,b=0;//a为随机值
//printf("a=%d,b=%d\n",a,b); tmd,没想到在这里翻车了
while(i<master->len && j < sub->len){//master,sub同时越过字符串
if(master->data[i] == sub->data[j]){
i++;//匹配
j++;
}
else{//不匹配的时候要回溯
i=i-j+1;
j=0;
}
}
printf("master->len=%d\n",master->len);
printf("sub->len=%d\n",sub->len);
printf("j=%d\n",j);//为什么j=1??
//循环完毕,进行判断
if(j == sub->len ){
printf("匹配成功.\n");
}
else{
printf("不匹配.\n");
}
}
int main(){
String* s=initString();
stringAssign(s,"heoh");
printString(s);
String* s1=initString();
stringAssign(s1,"he");
printString(s1);
forceMatch(s,s1);
return 0;
}
02kmp算法
2.1定义
更详细的算法解释:kmp算法描述
(1)next 数组的求解:就是找最大对称长度的前缀后缀,然后整体右移一位,初值赋为-1。
(2)而最大对称长度的前缀后缀怎么求呢?
上图为推导过程,具体的代码实现如下:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 5
typedef struct String{
char* data;//C里面没有字符串的概念,所以需要字符型指针来代替这个而且最后一个是\0结尾.
int len;
}String;
//初始化
String* initString(){
String* S=(String*)malloc(sizeof(String));
S->data=NULL;
S->len=0;
return S;
}
//data的数据需要一个输入函数,因此需要写一个输入函数
void stringAssign(String*s,char* data){
if(s->data){
free(s->data);
}
int len=0;//字符串有多长
char * temp=data;//找一个变量代替data
while(*temp){//data
len++;
temp++;//数组的第一个元素,顺序表的直接加一,不需要考虑指针
}
s->len=len;
//上面得到data的长度len,temp指向最后一个data[len-1];
if(len == 0){//为空
s->data=NULL;
//s->len=0;
}
else{
//有值
// s->len=len;
temp=data;
//开辟空间的理解还是不够
s->data=(char*)malloc(sizeof(char)*(len+1));//多一个存\0
//为什么要开辟空间呢?因为我要输入一个值,那么我希望得到一些内存空间。
for(int i=0;i<len;i++,temp++){
s->data[i]=*temp;//学习这种表示方式,*temp=data[i];
}
}
}
//输出字符串
void printString(String* s){
for(int i=0;i< (s->len);i++){
printf(i==0 ? "%c":"->%c",s->data[i]);//注意i==0!!
}
printf("\n");
}
//完成暴力匹配算法
void forceMatch(String* master,String* sub){
//定义两个指针
int i=0;
int j=0;//这样跟int i,j=0;有区别吗???
//int a,b=0;//a为随机值
//printf("a=%d,b=%d\n",a,b); tmd,没想到在这里翻车了
while(i<master->len && j < sub->len){//master,sub同时越过字符串
if(master->data[i] == sub->data[j]){
i++;//匹配
j++;
}
else{//不匹配的时候要回溯
i=i-j+1;
j=0;
}
}
printf("master->len=%d\n",master->len);
printf("sub->len=%d\n",sub->len);
printf("j=%d\n",j);//为什么j=1??
//循环完毕,进行判断
if(j == sub->len ){
printf("匹配成功.\n");
}
else{
printf("不匹配.\n");
}
}
//kmp算法:
int* getNext(String* s){
int* next =(int*)malloc(sizeof(int)*s->len);
int i=0;
int j=-1;
next[i]=-1;
while(i < s->len-1){
if(j == -1 || s->data[i] == s->data[j]){
i++;
j++;
next[i]=j;
}
else{
j=next[j];
}
}return next;
}
//kmp算法
void kmpMatch(String* master, String* sub, int* next) {
int i = 0;
int j = 0;
while (i < master->len && j < sub->len) {
if (j == -1 || master->data[i] == sub->data[j]) {
i++;
j++;
} else {
j = next[j];
}
}
if (j == sub->len) {
printf("kmp match success.\n");
} else {
printf("kmp match fail.\n");
}
}
//打印next
void printnext(int * next,int len){
for(int i=0;i<len;i++){
printf(i == 0 ? "%d":"->%d",next[i]+1);
}
printf("\n");
}
int main(){
String* s=initString();
stringAssign(s,"heosfhakfhfah");
printString(s);
String* s1=initString();
stringAssign(s1,"heos");
printString(s1);
int *next=getNext(s1);
printnext(next,s1->len);
forceMatch(s,s1);
kmpMatch(s,s1,next);
return 0;
}