KMP算法、manacher算法

1、KMP算法

KMP算法(Knuth-Morris-Pratt算法)是一种高效的字符串匹配算法,用于KMP算法(Knuth-Morris-Pratt算法)是一种高效的字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的主要思想是利用已知的部分匹配信息,避免在文本串中的多余比较。

KMP算法的核心是计算模式串的最长公共前后缀数组(next数组),然后根据next数组进行匹配。具体步骤如下:

  1. 初始化两个指针i和j,分别指向模式串和文本串的起始位置。
  2. 计算模式串的next数组。next[i]表示模式串前i个字符组成的子串的最长公共前后缀的长度。
  3. 当文本串中当前字符与模式串当前字符相等时,i和j都向右移动一位;否则,i不变,j向右移动一位。
  4. 如果j等于模式串的长度,说明找到了一个匹配,返回当前位置;否则,继续匹配下一个字符。
  5. 如果文本串已经遍历完毕,但仍未找到匹配,说明模式串不在文本串。
    int* getNext(string str2){
        int* Next=new int[str2.length()];
        if(str2.length()==0){
            return Next;
        }else if(str2.length()==1){
            Next[0]=-1;
            return Next;
        }else{
            Next[0]=-1;
            Next[1]=0;
            int cn=0,i=2;
            while(i<str2.length()){
                if(str2[cn]==str2[i-1]){
                    Next[i++]=++cn;
                }else if(cn>0){
                    cn=Next[cn];
                }else{
                    Next[i++]=0;
                }
            }
            return Next;
        }
    }
    
    int getTheIndexOf(string str1,string str2){
        if(str1.length()==0||str2.length()==0) return -1;
        int i=0,j=0;
        int *Next=getNext(str2);
        while(i<str1.length()&&j<str2.length()){
            if(str1[i]==str2[j]){
                i++;
                j++;
            }else if(Next[j]==-1){
                i++;
            }else{
                j=Next[j];
            }
        }
        return j==str2.length()?i-j:-1;
    }
    
    int main(){
        string str1,str2;
        cin>>str1>>str2;
        cout<<getTheIndexOf(str1,str2)<<endl;
        return 0;
    }
    

2、MANACHER算法 

Manacher算法是一种用于查找一个字符串中所有回文子串位置的线性时间复杂度算法。它的主要思想是将原字符串进行预处理,将每个字符的最长回文半径保存下来,然后利用这些信息来快速找到所有的回文子串。


string extend(string str1){
    string ans;
    for(int i=0;i<str1.length();i++){
        ans+=(str1.substr(i,1)+"#");
    }
    return ans.substr(0,ans.length()-1);
}

int GetLongestReLength(string str){
    if(str.length()==0){
        return 0;
    }else if(str.length()==1){
        return 1;
    }else{
        string ans=extend(str);
        int visited[ans.length()];
        for(int i=0;i<ans.length();i++){
            visited[i]=0;
        }
        int c=0;                        //c表示中点
        for(int i=1;i<ans.length();i++){//i扫描到的位置
            if(c+visited[c]<i){         //当i在c+visited[c]外,单纯在i点暴力扩
                int tmp=0;
                for(;i+tmp<ans.length()&&i-tmp>=0&&ans[i+tmp]==ans[i-tmp];tmp++);
                visited[i]=tmp-1;
                if(visited[i]>=visited[c]){
                    c=i;
                }
            }else{                      //当i在c+visited[c]内
                int anotheri=2*c-i;
                if(i+visited[anotheri]<c+visited[c]){
                    visited[i]=visited[anotheri];
                }else if(i+visited[anotheri]>c+visited[c]){
                    int tmp=0;
                    for(;i+tmp<ans.length()&&i-tmp>=0&&ans[i+tmp]==ans[i-tmp];tmp++);
                    visited[i]=tmp-1;
                    if(visited[i]>=visited[c]){
                        c=i;
                    }
                }else{
                    int tmp=visited[anotheri];
                    for(;i+tmp<ans.length()&&i-tmp>=0&&ans[i+tmp]==ans[i-tmp];tmp++);
                    visited[i]=tmp-1;
                    if(visited[i]>=visited[c]){
                        c=i;
                    }
                }
            }
        }
        int r=visited[c];
        for(int i=c+1;i<=c+visited[c];i++){
            if(ans[i]=='#') r--;
        }
        if(ans[c]=='#') return 2*r;
        else return 2*r+1;
    }
}

int main(){
    string str1;
    cin>>str1;
    cout<<GetLongestReLength(str1)<<endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值