160. 匹配统计

题目链接
cnt[i]表示与模式串匹配长度至少为i的文本串的后缀数目
(此时cnt[x]保存的是匹配长度>=x的位置个数 这样理解更清楚一点)
那么恰好匹配长度为x的数目就是cnt[i]-cnt[i+1],有点后缀和思想
参考题解

#include 
using namespace std;
void getnext(vector<int>&next, string pattern){
    next[0]=-1;
    int j=-1;
    for(int i=1;i<pattern.size();i++){
        while(j!=-1 && pattern[j+1]!=pattern[i]){
            j=next[j];
        }
        if(pattern[j+1]==pattern[i]){
            j++;
        }
        next[i]=j;
    }
}
int main(){
    
    int n,m,q;
    cin >> n >> m >> q;
    string text,pattern;
    cin >> text >> pattern;
    vector<int> next(m,-1);
    getnext(next,pattern);
    int cnt[200005]={0};
    int j=-1;
    for(int i=0;i<text.size();i++){
        while(j!=-1 && text[i]!=pattern[j+1]){
            j=next[j];
        }
        if(text[i]==pattern[j+1]){
            j++;
        }
        cnt[j+1]++;//pattern[0-j]匹配了text[i-j~i]串,至少匹配长度为j+1,(“至少”是因为下一个字符还可能匹配),同时pattern[0-next[j]]也匹配了text[i-next[j]~i]串...(相当于把以i位置结尾各个至少匹配长度的个数都+1)整体来看,最终cnt[j+1]加几次,cnt[next[j]+1]就会加几次,因此可以最后倒着枚举累加,降低时间复杂度
        if(j==m-1){
            j=next[j];
        }
    }
    for(int i=m;i>=1;i--){
        cnt[next[i-1]+1]+=cnt[i];//i表示匹配的长度,对应到next数组要-1
    }
    for(int i=0;i<q;i++){
        int tmp;
        cin >> tmp;
        cout << cnt[tmp]-cnt[tmp+1] << endl;
    }
    return 0;
}

你可能感兴趣的:(还是刷题,c++,算法)