利用KMP算法,求顺序表存储的两个字符串的最长公共子串

/*程序说明: * 程序是由顺序表实现,功能为查找两字符串中的最长公共子串; * 两条字符串分别由两个顺序表存储; * 查找思路是分解出短的那条字符串的全部连续子串(例如abc分解为abc,ab,a,bc,b,c), * 再使用kmp算法将该全部子串与长的那条字符串进行匹配,找到最长的那条子串; * 完成日期:2017.5.20 * 编译环境:visual studio 2015 */

#include<iostream>
using namespace std;
const int MaxNum = 100;
struct SeqString//顺序表结构
{
    int length;//长度
    char c[MaxNum];//存储数据
};
typedef struct SeqString* PSeqString;

PSeqString creatString();
void find(PSeqString t, PSeqString p);
int KMPmatch(PSeqString t, PSeqString p2, int* next);
void makenext(PSeqString p, int* next);
void display(PSeqString pstr);

int main()
{
    PSeqString p = new SeqString;
    p = creatString();
    PSeqString t = new SeqString;
    t = creatString();

    find(p, t);
    cin.get(); cin.get();//暂停
}

PSeqString creatString()//创建并初始化一条字符串
{
    PSeqString pstr = new SeqString;
    cout << "输入其中一个字符串:\n";
    cin >> pstr->c;
    pstr->length = strlen(pstr->c);
    return pstr;
}

void find(PSeqString t, PSeqString p)//查找公共子串
{
    PSeqString temp = new SeqString;
    if (t->length < p->length)//交换使得p串为更短的那个字符串
    {
        temp = t;
        t = p;
        p = temp;
    }
    int* next = new int[MaxNum];//next数组
    int len = 0, maxlen = 0, loc = 0;//len为子串长度,maxlen为匹配成功的最长子串长度,loc为开始匹配子串的首下标
    PSeqString p2 = new SeqString;
    int i, k, l; //i,j,k都是是字符串的下标

    //利用循环取不同的i和len,以达到取p不同的子字符串的目的
    for (int i = 0; i < p->length; i++)//改变i,此处i是p字符串的下标
    {
        for (len = p->length - i; len > 0; len--)//改变len
        {
            p2->length = len;
            for (k = 0, l = i; k < len; k++, l++)//使得p2为即将进行匹配的子串
            {
                p2->c[k] = p->c[l];
            }
            makenext(p2, next);//获取p2的next数组

            if (KMPmatch(t, p2, next) && len > maxlen)//子串匹配成功且len最大则保存len与i
            {
                maxlen = len;
                loc = i;
            }
        }
    }

    p2->length = maxlen;
    for (k = 0, l = loc; k < maxlen; k++, l++)//使得p2为最长公共子串
    {
        p2->c[k] = p->c[l];
    }

    cout << "最长的公共子串为: ";
    display(p2);
    delete(p2);
    delete(temp);
}

int KMPmatch(PSeqString t, PSeqString p2, int* next)//kmp算法字符串匹配
{
    int i = 0, j = 0;
    while (i < p2->length&&j < t->length)
    {
        if (i == -1 || p2->c[i] == t->c[j])
        {
            i++, j++;
        }
        else
            i = next[i];
    }
    if (i >= p2->length)
        return 1;
    else
        return 0;
}

void makenext(PSeqString p, int* next)//kmp算法求next数组
{
    int i = 0, k = -1;
    next[0] = -1;
    while (i < p->length - 1)
    {
        while (k >= 0 && p->c[i] != p->c[k])
            k = next[k];
        i++, k++;
        if (p->c[i] == p->c[k])
            next[i] = next[k];
        else
            next[i] = k;
    }
}

void display(PSeqString pstr)//显示pstr顺序表中的数据
{
    for (int i = 0; i < pstr->length; i++)
    {
        cout << pstr->c[i];
    }
}

《利用KMP算法,求顺序表存储的两个字符串的最长公共子串》

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/zero_d_slayer/article/details/72625347
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞