您的位置:首页 > 编程语言

KMP算法实现代码

2016-06-26 11:43 507 查看

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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: