题目链接

https://ac.nowcoder.com/acm/contest/7412/G

题目大意

字符串匹配。

解题思路

我的KMP详讲 更新于2020.10.21
一上来就想暴力,明知道暴力不行,还是想试试,毕竟不会别方法了。果不其然,过了80多的数据,没AC。
正解:KMP!(没听说过,百度了一下,发现真的是巨难!用了3h才勉强理解,但是代码还是自己写不出来,背过的)
(我实在讲不明白,直接放弃自己手写)
(教会我KMP的大佬讲解)
就本题而言,无非是把牛牛喜欢的字符串S作为模式串(即由j控制的字符串),多组输入的字符串作为文本串(即由i控制的字符串),同时在KMP函数里统计一下匹配到的最长子串,对应语句为 maxx=max(maxx,j);,理解了KMP实现过程之后会发现j的值为公共子串的长度,所以取j的最大值就是能扫描到的模式串S(即牛牛喜欢的字符串)的最长长度。累加输出。

函数模板

//获取next数组
void getnext(string s){
    nxt[0]=-1;//不能用next作为名字,因为c++中存在next
    int i=0,j=-1;
    int len=s.length();
    while(i<len-1){
        if(j==-1 || s[i]==s[j]){
            ++i;
            ++j;
            nxt[i]=j;
        }
        else j=nxt[j];    
    }    
}
//KMP,只是匹配的过程(根据题目要求进行变形)
void KMP(string s,string p){
    int i=0,j=0,maxx=0;
    int slen=s.length(),plen=p.length();
    while(i<slen && j<plen){
        if(j==-1 || s[i]==p[j]){
            ++i;
            ++j;
        }
        else j=nxt[j];
    }
}

AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
int nxt[N];
void getnext(string s){
    nxt[0]=-1;
    int i=0,j=-1;
    int len=s.length();
    while(i<len-1){
        if(j==-1 || s[i]==s[j]){
            ++i;
            ++j;
            nxt[i]=j;
        }
        else j=nxt[j];    
    }    
}
int KMP(string s,string p){
    int i=0,j=0,maxx=0;
    int slen=s.length(),plen=p.length();
    while(i<slen && j<plen){
        if(j==-1 || s[i]==p[j]){
            ++i;
            ++j;
            maxx=max(maxx,j);//唯一变化!关键语句!
        }
        else j=nxt[j];
    }
    return maxx;
}

ll ans;
string str,tmpstr;
int n;
int main(){
    cin>>str;
    getnext(str);
    cin>>n;
    while(n--){
        cin>>tmpstr;
        ans+=KMP(tmpstr,str);
    }
    cout<<ans<<endl;
}

优化代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
int nxt[N];
/*
void CreateNext(string p){
    nxt[1]=0;
    int i=1,j=0,len=p.size();
    p='.'+p;
    while(i<=len){
        if(j==0 || p[i]==p[j]){
            ++i,++j;
            nxt[i]=j;
        }
        else j=nxt[j];
    }
}
*/
void CreateNext(string p){
    nxt[1]=0;
    int i=1,j=0,len=p.size();
    p='.'+p;
    while(i<=len){
        if(j==0 || p[i]==p[j]){//通过i去更新nxt里面存储的位置 
            ++i;++j;
            if(p[i]==p[j]) nxt[i]=nxt[nxt[i]];//此时nxt[i]=j,因此 <=> nxt[i]=nxt[j];
            else nxt[i]=j;
        }
        else j=nxt[j];
    }
}
int Match(string s,string p){
    int i=1,j=1,happy=0,slen=s.size(),plen=p.size();
    s='.'+s;
    p='.'+p;
    while(i<=slen && j<=plen){
        if(j==0 || s[i]==p[j]) {happy=max(happy,j);++i;++j;}
        else j=nxt[j];
    }
//    cout<<happy<<endl;
    return happy;
}
string p,s;
int n,ans;
int main(){
    cin>>p>>n;
    CreateNext(p);
    for(int i=1;i<=n;i++){
        cin>>s;
        ans+=Match(s,p);
    }
    cout<<ans<<endl;
} 

暴力代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
vector<string> book;
string tmp_str,like;
int n;
ll ans;
int main(){
    cin>>like;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>tmp_str;
        book.push_back(tmp_str);
    }
    int vsize=book.size();
    int likesize=like.length();
    for(int i=0;i<vsize;i++){
        int maxx=0;
        int booksize=book[i].length();
        for(int j=0;j<booksize;j++){
            int p2=0,p1=j,cnt=0;
            while(p1<booksize && p2<likesize && book[i][p1]==like[p2]) p1++,p2++,cnt++;
            maxx=max(cnt,maxx);
        }
        ans+=maxx;
    //    cout<<maxx<<endl;    
    }
    cout<<ans<<endl;
}