KMP算法

KMP模板和一些典型题

  • 一 、模板
  • 二、无线传输
  • 三、记录详情
  • 四、 二叉树中的链表

一 、模板

这里的求next有两种写法,思路是一样的。
作者喜欢用第一种:

void calnext(string &s2) {
    nt[0]=-1;
    nt[1]=0;
    for(int i=2;i<s2.size();i++) {
        int t = i-1;
        while(t > 0 && s2[nt[t]] != s2[i-1]) {
            t=nt[t];
        }
        //for (int i=0 ;i
        //	cout << ne[i] << " ";
    	//}
        nt[i]=nt[t]+1;
    }
}

第二种求next写法:

 int i=2,cn=0;
     while (i<tstr.size()) {
         if (tstr[i-1]==tstr[cn]) {
             ne[i++]= ++cn;
         }else if (cn>0){
             cn=ne[cn];
         }else {
             ne[i++]= 0;
         }
     }

整体KMP写法(next求法+匹配)

//kmp算法
#include
using namespace std;
const int M = 1e5+5;
int nt[M];
void calnext(string &s2) {
    nt[0]=-1;
    nt[1]=0;
    for(int i=2;i<s2.size();i++) {
        int t = i-1;
        while(t > 0 && s2[nt[t]] != s2[i-1]) {
            t=nt[t];
        }
        //for (int i=0 ;i
        //	cout << ne[i] << " ";
    	//}
        nt[i]=nt[t]+1;
    }
}
void kmpnow(string &a,string &b){
    // cout<<"到达"<<'\n';
    int x=0,y=0;
    while (x<a.size()&&y<b.size()) {
        if (a[x]==b[y]) {
            x++,y++;
        }else if (y==0) {
            x++;
        }else {
            y=nt[y];
        }
    }
    if (y==b.size()) {
        cout<<x-y<<'\n';
    }else {
        cout<<"没有找到"<<'\n';
    }
}
int main() {
    ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    string s1,s2;
    cin>>s1>>s2;
    calnext(s2);
    kmpnow(s1,s2);
    return 0;
}

二、无线传输

无线传输题目
ans = n - next[n]
为什么不能更长呢?

#include
using namespace std;
const int N = 1e6+5;
int ne[N];
string s;
int l;
void calnext() {
    ne[0] = -1;
    ne[1] = 0;
    for (int i=2;i<=l;i++) {//这里多求一个位置
        int t = i - 1;
        while (t > 0 && s[ne[t]]!=s[i-1]) {
            t = ne[t];
        }
        ne[i]=ne[t]+1;
    }
    cout<<l - ne[l]<<'\n';//总长减去最后一个值的后一个位置的ne值
}
int main() {
    ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>l>>s;
    calnext();
    return 0;
}

三、记录详情

题目点击这里
栈+KMP混合使用
first:第一个串中的下标
second:第二个串中的下标

#include
using namespace std;
const int N = 1e6+5;
int ne[N];
string s,tstr;
// vector > st;
int sz=0;
struct st {
    int first, second;
    // st(int a, int b) : first(a), second(b) {}
    // st():first(0),second(0){}
}st1[N];
void calnext() {
    ne[0] = -1;
    ne[1] = 0;
    for (int i=2;i<tstr.size();i++) {
        int t = i - 1;
        while (t > 0 && tstr[ne[t]]!=tstr[i-1]) {
            t = ne[t];
        }
        ne[i]=ne[t]+1;
    }
}
int main() {
    ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>s>>tstr;
    calnext();
    int x=0,y=0;
    while (x<s.size()) {
        if (s[x]==tstr[y]) {
            st1[sz].first=x++,st1[sz].second=y++;
            sz++;
        }else if (y==0) {
            st1[sz].first=x++,st1[sz].second=-1;
            sz++;
        }else {
            y = ne[y];
        }
        if (y==tstr.size()) {
            sz-=tstr.size();
            if (sz) {
                y=st1[sz-1].second + 1;
            }else {
                y=0;
            }
        }
    }
    for (int i=0;i<sz;i++) {
        auto &p=st1[i].first;
        cout<<s[p];
    }
    return 0;
}

四、 二叉树中的链表

1367.二叉树中的链表

const int N = 2505;
class Solution {
public:
    int n,m,a[N];
    int ne[N];
    vector<int>h;
    bool isSubPath(ListNode* head, TreeNode* root) {
        n = cnt(root);
        change(head);
        m = h.size();
        calnext();
        return findTF(root,0);
    }
    bool findTF(TreeNode* root,int i){
        if(i == m){
            return true;
        }
        if(root == NULL){
            return false;
        }
        while(i>=0&&root->val!=h[i]){
            i=ne[i];
        }
        return findTF(root->left,i+1)|| findTF(root->right,i+1);
    }
    int cnt(TreeNode* root){
        if(root==NULL){
            return 0;
        }else{
            int l = cnt(root->left);
            int r = cnt(root->right);
            return l+r;
        }
    }
    void change(ListNode* head){
        while(head!=NULL){
            h.push_back(head->val);
            head=head->next;
        }
    }
    void calnext() {
        ne[0] = -1;
        ne[1] = 0;
        for (int i=2;i<h.size();i++) {
            int t = i - 1;
            while (t > 0 && h[ne[t]]!=h[i-1]) {
                t = ne[t];
            }
            ne[i]=ne[t]+1;
        }
    }

};

你可能感兴趣的:(KMP算法)