KMP 字符串匹配

理论参考:阮一峰老师http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

#include "stdafx.h"

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

void BuildPatchMatchTable(int *partMatchTable, char *findstr)
{
    int len = strlen(findstr);
    if (findstr == NULL)
        return;
    partMatchTable[0] = 0;

    string findstring = string(findstr);
    string tmpstr = "";
    vector<string> prefixVec;
    vector<string> suffixVec;

    for (int i = 2; i < len+1; i++)
    {
        tmpstr = findstring.substr(0,i);
        //前缀:
        for (int j = 1; j < i; j++)
            prefixVec.push_back(tmpstr.substr(0, j));
        //后缀:
        for (int j = 1; j < i; j++)
            suffixVec.push_back(tmpstr.substr(j));

        //共有元素的最大长度
        int maxsize = 0;
        for (int j = 0; j < prefixVec.size(); j++)
        {
            int length = 0;
            auto it = find(suffixVec.begin(), suffixVec.end(), prefixVec[j]);
            if (it != suffixVec.end())
                length = prefixVec[j].size();

            maxsize = max(length, maxsize);
        }
        partMatchTable[i - 1] = maxsize;
        prefixVec.clear();
        suffixVec.clear();
    }
}

int KMP(char *srcstr, char *findstr){
    int len = strlen(findstr);
    int *partMatchTable = new int[len];
    BuildPatchMatchTable(partMatchTable, findstr);

    int temp = strlen(srcstr) - strlen(findstr);
    int pos = 0;
    while (pos < temp)
    {
        int j = 0;
        for (int i = pos; i < (pos + len); i++)
        {
            if (srcstr[i] == findstr[i - pos])
            {
                ++j;
                if (j == len)
                {
                    delete partMatchTable;
                    return pos;
                }
            }
            else
            {
                if (j == 0){
                    pos = pos + 1;
                }
                else
                {
                    pos = pos + j- partMatchTable[j - 1];
                }
                break;
            }
        }
    }
    delete partMatchTable;
    return -1; //不存在
}

int _tmain(int argc, _TCHAR* argv[])
{

    char srcStr[] = "bbc abcdab abcdabcdabde";
    char findStr[] = "abcdabd";
    cout << "pos:" << KMP(srcStr, findStr) << endl;

    system("pause");
    return 0;
}
时间: 2024-10-23 23:56:25

KMP 字符串匹配的相关文章

Luogu P3375 【模板】KMP字符串匹配

P3375 [模板]KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整数

KMP字符串匹配

1 #include<iostream> 2 3 4 using namespace std; 5 6 #define MAX 255 7 8 typedef unsigned char BYTE; 9 10 typedef BYTE String[MAX+1]; 11 12 bool strAssign(String& strTemp,char* Temp); //定长字符串存储 13 bool strTravel(String& strTemp); //打印 14 void

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

P3375 模板 KMP字符串匹配

P3375 [模板]KMP字符串匹配 来一道模板题,直接上代码. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e6 + 5; int n, m; char s1[N], s2[N]; int nxt[N] ; void Get_next(char *s) { int j, L = strlen(s + 1); nxt[1] = j = 0; for(int i = 2; i

KMP字符串匹配 fzu2275重现赛POJ3167

KMP原理  点击 FZU 2275 Game 乍一看是个博弈的题目,实际上是重现里面比较简单的字符匹配. 只要B是0,那么A一定赢.只要A的长度小于B,那么B一定赢. 只有当A中可以搜索到B,也就是B或者B的反转是A的子串,那么A就可以赢. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <math.h> #inclu

FZU 2122 ——又见LKity——————【KMP字符串匹配】

Problem 2122 又见LKity Accept: 413    Submit: 1425Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 嗨!大家好,在TempleRun中大家都认识我了吧.我是又笨又穷的猫猫LKity.很高兴这次又与各位FZU的ACMer见面了.最近见到FZU的各位ACMer都在刻苦地集训,整天在日光浴中闲得发慌的我压力山大呀!于是,我准备为诸位编写一款小工具——LKity牌文本替

【洛谷】3375 KMP字符串匹配

[算法]KMP [题解][算法]字符串 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1000010,maxm=1010; char A[maxn],B[maxm]; int p[maxm],n,m; int main() { scanf("%s%s",A+1,B+1); n=strlen(A+1);m=strlen

洛谷—— P3375 【模板】KMP字符串匹配

题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值. 输

算法模板——KMP字符串匹配

功能:输入一个原串,再输入N个待匹配串,在待匹配串中找出全部原串的起始位置 原理:KMP算法,其实这个东西已经包含了AC自动机的思想(fail指针/数组),只不过适用于单模板匹配,不过值得一提的是在单模板大量匹配待匹配串时,这个会有相当大的优势,AC自动机虽然好想一些,但是在这一类问题上的性价比就略低了 1 var 2 i,j,k,l,m,n:longint; 3 a:array[0..100000] of longint; 4 s1,s2:ansistring; 5 begin 6 readl

P3375 【模板】KMP字符串匹配(全程注释,简单易懂)

题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值. 输