字符串匹配-KMP

来源:互联网 发布:apache服务器搭建 编辑:程序博客网 时间:2024/06/05 18:44

#include <iostream>

#include <string>

#include <cstring>

using namespacestd;

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];

            }

            elsef[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);

    return0;

}


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
原创粉丝点击