第九题:(1)设计Strcmp(s,t)算法,实现两个字符串s和t的比较(2)设计一个算法,在字符串str中查找子串substr最后一次出现的位置

#include<iostream>
using namespace std;

int* Next(string T){            
    int i = 0,j = 1;
    int tlen = T.length();
    int *N = new int[tlen];
    N[0] = 0;
    int counter = 1;
    while(j < tlen){
        if(T[i] == T[j]){
            N[counter] = 1+N[counter -1];
            i+=1;
            j+=1;
            counter += 1;
        }
        else{
            if(i == 0){
                N[counter] = 0;
                counter+=1;
                j+=1;
            }
            else{
                while(T[j] != T[i]&& i >0)
                    i = N[i];
                if(T[j] == T[i]){
                    N[counter] = N[i] + 1;
                    j+= 1;
                    i+=1;
                    counter += 1;
                }
                else{
                    N[counter] = 0;
                    j+=1;
                    counter += 1;
                }
            }
        }
    }
    return N;
}
int KMP(string T,string P,int pos){        //实际上是KMP的变式,可以由pos所指示的位置开始查找
     
    int p = 0,t = pos;
    int plen = P.length();
    int tlen = T.length();
    if(tlen < plen)
        return -1;
    int *n = new int[plen];
    n = Next(T);
   /* cout << "向量数组为:" ;
    for(int i = 0;i<tlen;i++)
        cout << n[i] << "    ";
        cout << endl;*/
    while(t<tlen&&p<plen){
        if(T[t]==P[p]){
            t+=1;
            p+=1;
        }
        else{
            if(p != 0)
                p = n[p-1];
            else
                t += 1;
        }

    }
    if(p == plen)
        return t-p;
    else
        return -1;
}
static int POS = 0;
int Search(string Str,string Substr){
    int res = -1;
    int i = 0;
    int len = Str.length();
    while(POS < len){
        i = KMP(Str,Substr,POS);
        POS += 1;
        if(i != -1)
            res = i;
    }
    return res;

}
int main(){
    string P,T;
    cout << "请输入目标字符串:" ;
    cin >> T;
    cout << endl << "请输入模式字符串:";
    cin >> P;
    int i = 0;
    i = Search(T,P);
    if(i==-1)
        cout << endl << "模式串不是目标串的子串!" << endl;
    else
        cout << endl << "模式串在目标串中最后一次出现的位置:" << i << endl;

return 0;
}

这个代码一开始想的是写一个KMP的变式,可以在指定的位置开始查找字串,然后在另一个函数中多次调用这个变式函数,得到最终结果。

后来我又想了一下其实没必要这么麻烦的。。只不过是把KMP算法改一下,如果匹配成功,则记录子串出现的位置,然后回溯,回到子串出现的位置的后一位,这样不断修改子串出现的位置,最终结果就是子串最后一次出现的位置啦!

修改后的代码在这里啦:

int KMP2(string str,string subst){
    int i = 0,j = 0,pos = -1;
    int* next = new int[subst.length()];
    Next(subst,next);
    for(int m = 0;m < subst.length();m++)
        cout << next[m] << "   ";
    while(i < str.length()){
        if(str[i] == subst[j]){
            if( j == subst.length()-1){
                pos = i -j;
                j = 0;
                i = i-j+ 1;                                 //这里很关键哦!
            }
            else{
                i += 1;
                j += 1;
            }
        }
        else{
            if(j!= 0)
                j = next[j];
            else
                i += 1;
        }
    }
    return pos;
}

 

    原文作者:查找算法
    原文地址: https://blog.csdn.net/zmk980305/article/details/84754835
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞