数据结构(三)——串之KMP算法

一、串类型的定义

一:串的基本概念

  • 串变量——串变量和其他类型变量一样
  • 串常量——串常量和整常数、实常数一样
  • 串值–串长–空串–空格串
  • 空格串和空串的不同之处:例如“ ”和“”分别表示长度为1的空白串和长度为0的空串
  • 子串–主串
  • 子串的序号——将子串在主串中首次出现时的该子串的首字符对应在主串中的序号,称为子串在主串中的序号
  • 串相等——只有当两个串的长度相等,且各个对应位置的字符都相同时才相等
    二、串的抽象数据类型定义
    串在计算机中有三种表示方式
  • 定长顺序存储表示——将串定义成字符数组,利用串名直接访问串值
  • 堆分配存储方式——地址连续的存储空间、动态分布,即用malloc()和free()函数来管理
  • 块链存储方式
    三、串的KMP算法
    串的KMP算法
    我对KMP的理解是基于以上链接中的内容。
    接下来放一下我的源码
    其中有关于串的基本操作和KMP的源码
#include 
#include 
#include 
#include 
#include 
#define MAX 100
typedef struct string
{
    char *ch;
    int length;
}Hstring,*Pstring;

int StAssign(Pstring T,char *chars);
int StrLength(Pstring T);
int StringCompare(Pstring T1,Pstring T2);
void StringClear(Pstring T);
Pstring StringConnect(Pstring T1,Pstring T2);
Pstring StringSon(Pstring T,int pos,int len);
void Print(Pstring T);
int KMP(Pstring T,char*S,int*next,int pos);
void GetNext(char*S,int*next);

int main()
{
    int next[MAX];
    int a,ret,pos,len;
    char S[MAX],S1[MAX],S2[MAX],S4[MAX];
    Pstring T,T1,T2,T3,T4;
    T=(Pstring)malloc(sizeof(Hstring));
    T1=(Pstring)malloc(sizeof(Hstring));
    T2=(Pstring)malloc(sizeof(Hstring));
    T3=(Pstring)malloc(sizeof(Hstring));
    T4=(Pstring)malloc(sizeof(Hstring));
    while(1)
    {
        printf("Please choose the choice you want:\n");
        printf("1.Establish String \n2.String Length \n3.String Compare \n");
        printf("4.String Clear \n5.String Connect \n6.String's Son \n");
        printf("7.KMP\n");
        scanf("%d",&a);
        getchar();
        switch(a)
        {
        case 1:
            gets(S);
            ret=StAssign(T,S);
            if(ret==1)
            {
                printf("Success!\n");
            }
            break;
        case 2:
            ret=StrLength(T);
            printf("The string's length is: %d\n",ret);
            break;
        case 3:
            printf("Please input the string 1:   ");
            gets(S1);
            StAssign(T1,S1);
            printf("Please input the string 2:   ");
            gets(S2);
            StAssign(T2,S2);
            ret=StringCompare(T1,T2);
            if(ret>0)
            {
                printf("The T1 is bigger than T2.\n");
            }
            else if(ret<0)
            {
                printf("The T2 is bigger than T1.\n");
            }
            else
            {
                printf("The two string is equal.\n");
            }
            StringClear(T1);
            StringClear(T2);
            break;
        case 4:
            StringClear(T);
            break;
        case 5:
            printf("Please input the string 1:   ");
            gets(S1);
            StAssign(T1,S1);
            printf("Please input the string 2:   ");
            gets(S2);
            StAssign(T2,S2);
            T3=StringConnect(T1,T2);
            Print(T1);
            Print(T2);
            Print(T3);
            StringClear(T1);
            StringClear(T2);
            StringClear(T3);
            break;
        case 6:
            printf("please input the position and the length:   ");
            scanf(" %d %d",&pos,&len);
            T4=StringSon(T,pos,len);
            if(T4->length!=0)
            {
                Print(T4);
                StringClear(T4);
            }
            break;
        case 7:
            printf("Please input the son string want to search:   ");
            gets(S4);
            printf("Please input the position you want to search:    ");
            scanf(" %d",&pos);
            GetNext(S4,next);
            ret=KMP(T,S4,next,pos);
            if(ret!=-1)
            {
            printf("the position is %d",ret);
            }
            else
            {
                printf("The position is not existence.\n");
            }
            free(S4);
            break;
        default:
            exit(0);
        }
    }
}

int StAssign(Pstring T,char *chars)//创建串
{
    char*p=chars;
    int i,j;
    for(i=0;*p;++p,++i);//计算串有多长
    if(i==0)
    {
        T->length=i;//当串为空时
    }
    else//当串不为空时
    {
        T->length=i;
        T->ch=(char*)malloc(i*sizeof(char));
    }
    assert(T->ch);
    for(j=0;j<T->length;j++)
    {
        T->ch[j]=chars[j];
    }
    return 1;
}

int StrLength(Pstring T)//返回串长度
{
    return T->length;
}

int StringCompare(Pstring T1,Pstring T2)//串的比较,T1>T2,返回值大于0
{
    int i;
    for(i=0;i<T1->length&&i<T2->length;i++)
    {
        if(T1->ch[i]!=T2->ch[i])//出现字符不同的情况
            return T1->ch[i]-T2->ch[i];
    }
    return T1->length-T2->length;//出现字符相同的情况
}

void StringClear(Pstring T)//清除串的内存
{
    if(T->ch)
    {
        free(T->ch);
    }
    T->length=0;
}

Pstring StringConnect(Pstring T1,Pstring T2)//将T2连接到T1后面
{
    Pstring T;
    int i=0,j=0,k;
    T->ch=(char*)malloc((T1->length+T2->length)*sizeof(char));
    while(T1->ch[i])//存入T1
    {
        T->ch[i]=T1->ch[i];
        i++;
        k=i;
    }
    while(T2->ch[j])//存入T2
    {
        T->ch[k]=T->ch[j];
        j++;
        k=i+j;
    }
    T->length=k;
    return T;
}

Pstring StringSon(Pstring T,int pos,int len)//从第pos位置开始复制长度为len子串
{
    Pstring T1;
    T1=(Pstring)malloc(sizeof(Hstring));
    int i,j;
    T1->length=0;
    if(pos<1||pos>(T->length-len)||len<0)//合法判断
    {
        printf("Wrong!!!\n");
        return T1;
    }
    else
    {
        for(i=pos-1,j=0;i<pos+len-1;i++,j++)//复制子串
        {
            T1->ch[j]=T->ch[i];
        }
        T1->length=len;
        return T1;
    }
}

void Print(Pstring T)//打印串
{
    int i;
    printf("The string is:      ");
    for(i=0;i<T->length;i++)
    {
        printf("%c",T->ch[i]);
    }
    printf("\n");
}

void GetNext(char*S,int*next)//求next的值
{
    int i=0,j=-1;//初始化
    next[0]=-1;//直接使next【0】=-1,便于后面操作
    while(i<strlen(S))//当i小于串长时
    {
        if(j==-1||S[i]==S[j])//如果位置i无相同的前缀或者i位置和j位置相同时
        {
            ++i;//主模式串左移一位
            ++j;//副模式串左移一位
            next[i]=j;//副模式串上的位置值给主模式串上的i位置的next
        }
        else
        {
            j=next[j];//进行回溯判断
        }
    }
}

int KMP(Pstring T,char*S,int*next,int pos)
{
    int i,j=0;
    i=pos-1;//i移到pos位置
    int len = T->length, l = strlen(S);
    while(i<len&&j<l)//T串走完或者S串走完
    {
        if(j==-1||T->ch[i]==S[j])//判断是否为整串当前位置不匹配或者模式串当前位置和主串匹配
        {
            ++i;
            ++j;
        }
        else
        {
            j=next[j];//回溯寻找前后缀相同的位置
        }
    }
    if(j==strlen(S))
        return i-j+1;
    else
        return -1;
}

你可能感兴趣的:(数据结构,应用)