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