字符串匹配-KMP

#include <iostream>

#include <string>

#include <cstring>

using namespace std;

const int maxn = 10005;

int f[maxn];


void getf1(string p)//可判断周期及循环数

{

    memset(f, -1, sizeof(f));

    f[0] = f[1] = 0;

    for (int i = 1; i < p.size(); i ++) {

        int j  = f[i];

        while (j && p[i] != p[j]) {

            j = f[j];

        }

        f[i + 1] = p[i] == p[j] ? j + 1 : 0;

    }

    

    

    for (int i = 1; i <= p.size(); i ++) {

      //  cout << f[i] << " " ;

        if (i % (i - f[i]) == 0 && f[i] > 0) {

            cout << i - f[i] << " " << i / (i - f[i]) << endl;//周期长度 周期数

        }

    }

    cout << endl;

}//getf1()

void match1(string t,string p)

{

    getf1(p);

    int j = 0;

    for (int i = 0; i < t.size(); i ++) {

        while (j && t[i] != p[j]) {

            j = f[j];

        }

        if (t[i] == p[j]) {

            j ++;

        }

        if (j == p.size()) {

            cout << i - j + 1 << endl;

        }

    }

}//match1()

void getf3(string p)//据说省时

{

    memset(f, -1, sizeof(f));

    f[0] = f[1] = 0;

    int i = 1,j = 0;

    while(i < p.size()){

        if (j == 0 || p[i] == p[j]) {

            i ++;j ++;

            if (p[i] == p[j]) {

                f[i] = f[j];

            }

            else f[i] = j;

        }

        else j = f[j];

    }

    

}//getf3()


void match3(string t,string p)

{

   getf3(p);

    int i = 0,j = 1;

    while(i <= t.size() && j <= p.size()) {

        if (j == 0 || t[i] == p[j]) {

            i ++;j ++;

        }

        else j = f[j];

        if (j == p.size()) {

            cout << i - j << endl;

        }

        

    }

   

}//match23()



int main()

{

   string s,t;

   cin >> s >> t;

   getf1(s);

    match1(t, s);

 getf3(s);

    match3(t, s);

    return 0;

}


KMP就像dfs,只是方法,题意变化,需要技巧转化。

poj1961

求给定字符串s,前i个字符,是否存在是字符串t的循环,循环次数k>1。求每种t的长度和k。

先求失配数组f[]。若i失配,则回到f[i],则s[f[i]..i]是s[1..i]的某个前缀,s[1..i]可能存在长度为(i - f[i])的字符串循环。

(i - f[i]) * k = i得到i % (i - f[i]) = 0。

且k > 1,即f[i] > 0。

poj2752

给定字符串s,求所有字符串a,为s的前缀后缀。即求所有k,使s[1..k] = s[sz - k + 1..sz]

失配数组f[].

q1 = f[sz],即s[1..q1] 与s[1..sz]最后q1个字符相同

q2 = f[q1],即s[1..q2] 与s[1..q1]最后q2个字符相同,即s[1..q2]与s[1..sz]最后q2个字符相同,即s[1..q2]同时为s的前缀后缀。

以此类推,至q = f[qx] = 0,没有一个字符相同,退出。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值