Extended KMP (explain + + template example)

Before reading this article, we assume that you have mastered the KMP: n + 1 times the probe in the definition.

Introduction: Extended KMP is doing

KMP problem is solved extended length of each of the longest common prefix and suffix string pattern string P of the source S and the array extend answer solved, e.g., ababac array and extend aba is 303,010, where extend [i] represents the s [i: 5] (i starts from 0) and P [0: 2] of the length of the longest common prefix.

Define next array

Unlike here next array of the KMP.

Next [i] represents the length of the longest common prefix and suffix i p from the start of p, i.e., p-p request the KMP expansion, can be found in 2019 the Multi-Contest The University Training. 5 - 1006 - String matching .

Let's assume that the array has been next to seek extend, because the next method is seeking an array and extend the same.

Extended KMP

Recursive: Known extend [i-1], how to seek extend [i]?

We assume that at the front, the matching to the farthest right coordinates Last, from the first start of the match, say s [first: last] = p [0: last-first]. Release can be s [i: last] = p [i-first: last-first], but this is not the beginning of the match, and p, which could not, we take extend [i] = min (last-i + 1, next [ i-first]), take a look at p [i-first: last-first] and p have the same number at the beginning. Back then detect extend [i] can not be bigger, this piece violence, do not forget last update first and last.

Initial: Good Dafa violence

P and s violence detecting the maximum length of the common prefix extend [0].

Seeking next array

the same as above. The next 0 position must be of length p, the initial value is set to 0 last code is to avoid the initialization.

example

hdu2328

To a bunch of strings, find the longest common string.

Find a shortest string of violence to obtain each suffix, and all string matching, each extend to find the biggest, the smallest overall take is one answer, find all the answers in the length of the longest lexicographically smallest, is the answer.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<iostream>
#define ll long long
#define db double
#define ioss ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int n,cnt;
ll ext[220],nex[220];
string skr[4020];
string ans[4020];
void getNext(string &strp,ll nextt[]){
    ll pl=strp.size();
    ll fir=0,las=0;
    nextt[0]=pl;
    for(ll i=1;i<pl;i++) {
        nextt[i] = min(las - i + 1, nextt[i - fir]);
        if (nextt[i] < 0) nextt[i] = 0;
        while (i+nextt[i]<pl && strp[nextt[i]] == strp[i + nextt[i]]) {
            nextt[i]++;
        }
        if (i + nextt[i] - 1 > las) {
            las = i + nextt[i] - 1;
            fir = i;
        }
    }
}
void exKMP(string &strp,string &strs,ll nextt[],ll extt[]){
    //cout<<"start exKMP:"<<endl;
    getNext(strp,nextt);
    ll pl=strp.size(),sl=strs.size();
    ll fir=0,las=-1,mnl=min(sl,pl);
    //cout<<strp<<endl<<strs<<endl;
    while(las<mnl-1&&strp[las+1]==strs[las+1]){
        las++;
        //cout<<"init++"<<endl;
    }
    extt[0]=las+1;
    for(ll i=1;i<sl;i++){
        extt[i]=min(las-i+1,nextt[i-fir]);
        if(extt[i]<0) extt[i]=0;
        while(extt[i]<pl && i+extt[i]<sl && strp[extt[i]]==strs[i+extt[i]]){
            extt[i]++;
        }
        if(i+extt[i]-1>las){
            las=i+extt[i]-1;
            fir=i;
        }
    }
}
int main() {
    //ioss;
    //freopen("1.in","r",stdin);
    //freopen("2.out","w",stdout);
    while(scanf("%d",&n)==1&&n){
        cnt=0;
        int mnlen=300,mnlenx;
        for(int i=1;i<=n;i++) {
            cin >> skr[i];
            if (skr[i].size() < mnlen) {
                mnlen = skr[i].size();
                mnlenx = i;
            }
        }
        for(int i=0;i<skr[mnlenx].size();i++){
            ll mn=1e10;
            string cur=skr[mnlenx].substr(i);
            //out<<i+1<<": cur= "<<cur<<endl;
            for(int j=1;j<=n;j++){
                ll mx=0;
                exKMP(cur,skr[j],nex,ext);
                /*cout<<"nex: ";
                for(int k=0;k<cur.size();k++){
                    cout<<nex[k]<<' ';
                }
                cout<<endl;
                cout<<"ext: ";*/
                for(int k=0;k<skr[j].size();k++){
                    //cout<<ext[k]<<' ';
                    mx=max(mx,ext[k]);
                }
                //cout<<endl;
                mn=min(mn,mx);
                //cout<<"mn = "<<mn<<endl;
            }
            if(mn>0){
                if(cnt==0||(mn==ans[1].size())){
                    ans[++cnt]=cur.substr(0,mn);
                }
                else if(mn>ans[1].size()){
                    cnt=0;
                    ans[++cnt]=cur.substr(0,mn);
                }
            }
        }
        if(cnt){
            sort(ans+1,ans+1+cnt);
            cout<<ans[1]<<endl;
        }
        else cout<<"IDENTITY LOST"<<endl;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/sz-wcc/p/11331361.html