题意:就是找第二个串在第一个串中出现的次数。
思路:kmp 对于如果T串只有1个或者两个字符就可以直接暴力了。但是对于有三个的字符就不可以了。那么把问题转化一下,就是去掉T串的首字符和尾字符,那么肯定其他的字符一定是相等的并且个数相等,那么我就直接kmp找出去掉首尾后在S中出现的个数,并记录下标,那么就可以最后再judge一下S中的首尾是否大于等于T中的首尾。kmp理解不到位就被kmp耍成傻逼。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int ,int > pii;
const int N =2e5+5;
int n,m;
int nn,mm;
char s[10];
ll cc;
ll cnt[N];
ll cnt1[N];
int num[N];
int num1[N];
int nxt[N];
int tmp[N];
ll tmpc[N];
vector<pii >ve;
void kmp_pre(int T[],ll cc[],int len)
{
int i,j;
i=0;
j=nxt[0]=-1;
while(i<len)
{
while(j!=-1&&( T[i]!=T[j]||cc[i]!=cc[j] )) j=nxt[j];
nxt[++i]=++j;
}
}
void kmp_count(int T[],ll c2[],int S[],ll c1[],int len)
{ // 返回T 在S 中出现的次数
int i,j;
kmp_pre(T,c2,len);
i=1; j=0;
for(i = 1; i <= nn; i++)
{
while(j > 0 && ( S[i] != T[j] || c1[i] != c2[j] )) j = nxt[j];
if(S[i] == T[j] && c1[i] == c2[j]) j++;
if(j == len)
{
//cout<<"id "<<i<<endl;
//cout<<"L "<<i-len<<" R "<<i+1<<endl;
ve.push_back(pii(i-len,i+1));
j = nxt[j];
}
}
}
int main()
{
num[0]=num1[0]=-1;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld-%s",&cc,s);
int id=s[0]-'a'+1;
if(num[nn]==id){
cnt[nn]+=cc;
}
else{
num[++nn]=id;
cnt[nn]=cc;
}
}
for(int i=1;i<=m;i++){
scanf("%lld-%s",&cc,s);
int id=s[0]-'a'+1;
if(num1[mm]==id){
cnt1[mm]+=cc;
}
else{
num1[++mm]=id;
cnt1[mm]=cc;
}
}
ll ans=0;
if(mm==1){
int id=num1[1];
cc=cnt1[1];
for(int i=1;i<=nn;i++){
if(num[i]==id&&cnt[i]>=cc)
{
ans+=1ll*(cnt[i]-cc+1);
}
}
printf("%lld\n",ans);
return 0;
}
else if(mm==2){
for(int i=1;i<nn;i++){
if(num[i]==num1[1]&&cnt[i]>=cnt1[1]&&num[i+1]==num1[2]&&cnt[i+1]>=cnt1[2]){
ans++;
}
}
printf("%lld\n",ans);
return 0;
}
else{
//cout<<"nn "<<nn <<" mm "<<mm<<endl;
int len=0;
for(int i=2;i<mm;i++){
//printf("%c",num1[i]-1+'a');
tmp[len]=num1[i];
tmpc[len++]=cnt1[i];
}
kmp_count(tmp,tmpc,num,cnt,len);
int sz=ve.size();
for(int i=0;i<sz;i++){
int l,r;
l=ve[i].first; r=ve[i].second;
if((num[l]==num1[1]&&cnt[l]>=cnt1[1])&&(num[r]==num1[mm]&&cnt[r]>=cnt1[mm])){
ans++;
}
}
printf("%lld\n",ans);
}
return 0;
}
/*
20 10
1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a
1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b 1-a 1-b
*/