KMP算法实现代码

2 篇文章 0 订阅

KMP算法实现

昨天看到一个快速字符串查找的思路---KMP,感觉挺有意思的,就实现来试试,下面是代码:

 

  • 环境: windows7 + Qt Creator3.4.2 + Qt5.5.0
  • 如果想看算法解释过程的请看这里KMP原理

 

main.cpp:

 

#include "mainwindow.h"
#include <QApplication>

#define SRC "abcdefghigklmnopqrstuvwxyz"
#define MATCHSTR "yzz"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString src, SubStr;
    src = SRC;
    SubStr = MATCHSTR;
    MainWindow w(src, SubStr);
    w.show();

    qDebug()<<"matcher num = "<<w.Matcher();



    return a.exec();
}


mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "string.h"


#include <QDebug>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QString &src, QString &sub);
    ~MainWindow();

    int Matcher();

private:
    void CalMatchTable();

private:

    QString SrcStr, SubStr;
    int *Matchlen;
};

#endif // MAINWINDOW_H

 

 

 

mainwindow.cpp

 

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QString &src, QString &sub) :
    SrcStr(src),
    SubStr(sub)
{

    Matchlen = new int[SubStr.size()];
    //这里需要bzero?
    Matchlen[0] = 0;
//    bzero();
    memset(Matchlen, 0, sizeof(int)*SubStr.size());
}

MainWindow::~MainWindow()
{
    if(Matchlen != NULL)
    {
        delete Matchlen;
        Matchlen = NULL;
    }
}

/**
 * return: 第一次匹配到的起始位置或者-1(没有匹配到)
 */
int MainWindow::Matcher()
{
    int index;

    CalMatchTable();

    for(int j = 0; j<SubStr.size(); j++)
        qDebug("SubStr %d = %d\n", j, Matchlen[j]);


    for(int i=0; i<SrcStr.size(); )
    {
        index = 0;
        if(SrcStr.at(i) != SubStr.at(0))
        {            
            i++;
            continue;
        }
        else
        {
            if( SubStr.size() == 1 )
            {
                return i;
            }

            for(int j=1; j<SubStr.size(); j++ )
            {
                //防止访问源字符串越界
                if(i+j >= SrcStr.size())
                    return -1;

                if(SrcStr.at(i+j) == SubStr.at(j))
                {
                    if( (j+1) == SubStr.size() )
                    {
                        return i;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    //移动位数 = 已匹配的字符数 - 对应部分的匹配值
                    index = j - Matchlen[j-1];
                    i += index;

                    break;
                }
            }
        }
    }
    return -1;
}

/**
 * 计算出部分匹配值(partial Match Table)
 */
void MainWindow::CalMatchTable()
{
    int num;
    QString substr;
    QStringList prefix, suffix;

    for( int i=1; i<SubStr.size(); i++ )
    {
        substr = SubStr.left(i+1);
        qDebug()<<"substr = "<<substr;

        //计算出前后缀
        //j: 1 -> strlen(substr)
        for(int j=1; j<substr.size(); j++)
        {
            prefix << substr.left(j);
            suffix << substr.right(substr.size()-j);
        }

        num = prefix.size();
        //前后缀对比共有元素,并对Matchlen数组赋值
        for(int k=0; k<num; k++)
        {
            if(prefix.at(k) == suffix.at(num-1-k))
            {
//                Matchlen[i]++;//这里可以么?
                Matchlen[i] = Matchlen[i] + 1;
            }
        }

        substr.clear();
        prefix.clear();
        suffix.clear();
    }
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值