DS串应用--KMP算法

关于KMP算法

字符串匹配算法,emmm,网上很多介绍,有兴趣的搜一搜就有了,直接上题吧~


问题 A: DS串应用--KMP算法

题目描述

学习KMP算法,给出主串和模式串,求模式串在主串的位置

输入

第一个输入t,表示有t个实例
第二行输入第1个实例的主串,第三行输入第1个实例的模式串
以此类推

输出

第一行输出第1个实例的模式串的next值
第二行输出第1个实例的匹配位置,位置从1开始计算,如果匹配成功输出位置,匹配失败输出0
以此类推

样例输入

3
qwertyuiop
tyu
aabbccdd
ccc
aaaabababac
abac

样例输出

-1 0 0
5
-1 0 1
0
-1 0 0 1
8


问题 B: DS串应用--串替换

题目描述

给出主串、模式串、替换串,用KMP算法找出模式串在主串的位置,然后用替换串的字符替换掉模式串
本题只考虑一处替换的情况,如果你想做的完美一些,能够实现多处替换那
可能需要考虑模式串和替换串长度不一致的情况

输入

第一个输入t,表示有t个实例
第二行输入第1个实例的主串,第三行输入第1个实例的模式串,第四行输入第1个实例的替换串
以此类推

输出

第一行输出第1个实例的主串
第二行输出第1个实例的主串替换后结果,如果没有发生替换就输出主串原来的内容。
以此类推

样例输入

3
aabbccdd
bb
ff
aaabbbccc
ddd
eee
abcdef
abc
ccccc

样例输出

aabbccdd
aaffccdd
aaabbbccc
aaabbbccc
abcdef
cccccdef


问题 C: 串应用- 计算一个串的最长的真前后缀

题目描述

给定一个串,如ABCDAB,则 ABCDAB的真前缀有:{ A, AB,ABC, ABCD, ABCDA } ABCDAB的真后缀有:{ B, AB,DAB, CDAB, BCDAB } 因此,该串的真前缀和真后缀中最长的相等串为AB,我们称之为该串的“最长的真前后缀”。 试实现一个函数string matched_Prefix_Postfix(string str),得到输入串str的最长的真前后缀。若不存在最长的真前后缀则输出empty

输入

第1行:串的个数 n 第2行到第n+1行:n个字符串

输出

n个最长的真前后缀,若不存在最长的真前后缀则输出empty。

样例输入

6
a
ab
abc
abcd
abcda
abcdab

样例输出

empty
empty
empty
empty
a
ab


问题 D: DS串应用—最长重复子串

题目描述

求串的最长重复子串长度。例如:abcaefabcabc的最长重复子串是串abca,长度为4。

输入

测试次数t
t个测试串

输出

对每个测试串,输出最长重复子串长度,若没有重复子串,输出-1.

样例输入

3
abcaefabcabc
szu0123szu
szuabcefg

样例输出

4
3
-1
╭( ′• o •′ )╭☞警察叔叔!就是这个人!悄咪咪改了题目


以下是绿色健康的代码 (゚∀゚)☞

#include
using namespace std;

class myString{
private:
    string mainstr;
    int size;
    void getnext(string p,int next[]){
        int i=1;
        next[0]=-1;
        next[1]=0;
        int j=0;
        while(i<(int)p.length()){
            if(j==-1||p[i]==p[j]){
                ++i;
                ++j;
                next[i]=j;
            }
            else
                j=next[j];
        }
    }
   int KMPFind(string p,int pos,int next[]){
     int i=pos;
     int j=0;
     while(i<(int)mainstr.length()&&j<(int)p.length()){
        if(j==-1||mainstr[i]==p[j]){
            ++i;
            ++j;
        }
        else
            j=next[j];
    }
    if(j>=(int)p.length())
        return i-j+1;
    else
        return -1;
  }
public:
    myString(){
        size=0;
        mainstr="";
    }   
    ~myString(){
        size=0;
        mainstr=""; 
    }
    void setval(string p){
        mainstr="";
        mainstr.assign(p);
        size=(int)mainstr.length();
    }
    int KMPFindSubstr(string p,int pos){
        int i;
        int L=p.length();
        int *next =new int[L + 1];
        getnext(p,next);
       /* for(i=0;inext[i]?ans:next[i];
        return ans;
    }//最长重复字串(重叠)
};

int main(){
   /* int t;
    cin>>t;
   while(t--){//模式串位置
        string s;
        cin>>s;
        myString S;
        S.setval(s);
        string p;
        cin>>p;
        cout<>t;
    while(t--){//模式串替换
        string s;
        cin>>s;
        myString S;
        S.setval(s);
        string p;
        cin>>p;
        int index=S.KMPFindSubstr(p,0);
        string ps;
        cin>>ps;
        cout<>t;
    while(t--){//最长的真前后缀字串
        string s;
        cin>>s;
        myString S;
        S.setval(s);
        cout<>t;
    while(t--){////最长重复字串(重叠)
        string s;
        cin>>s;
        myString S;
        S.setval(s);
        int ans=S.Maxsubstr();
        if(ans==0)
            ans--;
        cout<

多说两句

原本问题D是要求不重叠的最长重复字串,上面的代码求出来的是最长重复字串(重叠),因为用next数组来求真的太简单了,要求不重叠的比较复杂……懒得一匹_(:з」∠) _


给大佬递茶.jpg

o(*≧▽≦)ツ┏━┓
最长重复字串(不重叠),由不留名的╭( ′• o •′ )╭☞XXX大佬提供
蒟蒻瑟瑟发抖﹙ˊ_>ˋ﹚

#include 
using namespace std;
const int N=5000+15;

string s, p;
int  n[N];

void getnext(const string& p){
    n[0] = -1;
    int k = -1, i = 0;
    while(i < (int)p.size()){
        if(k == -1 || p[k] == p[i]){
            i++;
            k++;
            n[i] = k;
        }else{
            k = n[k];
        }
    }
}

int kmpMatch(const string& p, string& s){
    int j = 0, i = 0;
    int ret = 0;
    while(i < (int)s.size()){
        if(j == -1 || p[j] == s[i]){
            i++;
            j++;
        }else{
            j = n[j];
        }  

        if(j == (int)p.size()){
            ret++;
            j = 0;
        }
    }
    return ret;
}

bool check(string s, int len){
    for(int i = 0; i < (int)s.size() - len; i++){
        getnext(s.substr(i, len));
        if(kmpMatch(s.substr(i, len), s) >= 2)
            return true;
    }
    return false;
}

int main(){
    int t;
    cin >> t;
    while(t--){
        cin >> s;
        int k = 1, r = (int)s.size();
        int ans = -1;
        while(k <= r){
            int m = (k + r) >> 1;
            if(check(s, m)){
                ans = m;
                k = m + 1;
            }else{
                r = m - 1;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

你可能感兴趣的:(DS串应用--KMP算法)