http://tjuacm.chaosheng.top/problem.php?id=1259
https://vjudge.net/problem/HDU-2594
字符串匹配KMP,太不熟练了,这个算法一直一知半解。
参考:
https://blog.csdn.net/weixin_44606952/article/details/97654887?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.baidujs&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.baidujs

先发一个暴力,WA有没有处理好的情况

llljs
mkllll
会输出0,但是实际应该是3。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 50010;

int main(){
    string s1, s2;
    while(cin >> s1 >> s2){
        //cin >> s2;
        int n = s1.size(); 
        int m = s2.size();
        if(n == 0 || m == 0){
            printf("0\n");
            continue;
        }
        int i = 0, j = 0;
        int len = 0;
        while(i < n && j < m){
            if(s1[i] == s2[j]){
                i++;
                j++;
                len++;
            }else{
                i = 0;
                j++;
                len = 0;
            }
            //printf("i = %d j = %d len = %d \n", i, j, len);
        } 

        if(j == m && len != 0){
            printf("%s %d\n", s1.substr(0, len).c_str(), len);
        }else{
            printf("0\n");
        }
    }
    return 0;
}

AC代码,用到KMP

KMP的next数组讲解 https://www.bilibili.com/video/BV1jb411V78H?from=search&seid=4819368457483381295
实现 https://blog.csdn.net/loterior/article/details/79104602

这个题是KMP的应用。本质上就是找前一个字符串的前缀和后一个字符串的后缀相同的串,使用 KMP 进行匹配时,注意当模式串 s1 到达结尾时,需要更新指针位置,返回值也需要返回前缀位置
kmp就是一个不断匹配的过程,但是当第一个字符串(就是要求next数组的)长度小于第二个字符串时,会出现匹配突然断了的情况,这个时候的,就要j=next[j],重新找到最近的点继续匹配,一直匹配到最后,既然要匹配到最后,那么肯定能够知道前缀和后缀的最大匹配,也就是最后的j值

参考 https://blog.csdn.net/u011815404/article/details/87983299

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 50010;

int nextt[N];

void getNext(string s){
    int n = s.size();
    int i = 0, j = -1;
    nextt[i] = j;
    while(i < n){
        if(j == -1 || s[i] == s[j]){
            i++;
            j++;
            nextt[i] = j;
        }else{
            j = nextt[j];
        }
    }
} 

int kmp(string s2, string s1){
    getNext(s1);
    int n = s1.size(); 
    int m = s2.size();
    int i = 0, j = 0;
    while(i < m && j < n){
        if(j == -1 || s2[i] == s1[j]){
            i++;
            j++;
            if(j == n && i != m){//当模式串到达结尾时,回到指定位置
                j = nextt[j];
            }
        }else{
            j = nextt[j];
        }
    }

    return j; //返回前缀的位置 
}

int main(){
    string s1, s2;
    while(cin >> s1 ){
        cin >> s2;
        int n = s1.size(); 
        int m = s2.size();
        if(n == 0 || m == 0){
            printf("0\n");
            continue;
        }

        int res = kmp(s2, s1);  
        if(res != 0){
            printf("%s %d\n", s1.substr(0, res).c_str(), res);
        }else{
            printf("0\n");
        }
    }
    return 0;
}