首先要把相同的缩到一起,然后考虑就是一个简单的匹配。
注意到b串两端的字符在a串里匹配可能比a串里那一块少。解决办法就是先把b的两端扣掉匹配,每次匹配成功时判断一下就好了。
b的长度≤2 直接特判掉。
#include<cstdio>
#include<algorithm>
#define Fir first
#define Sec second
#define mp(x,y) make_pair(x,y)
using namespace std;
const int maxn=200005;
typedef long long LL;
int n,m;
LL ans;
pair<LL,char> a[maxn],b[maxn];
void Pre(pair<LL,char> a[],int &n){
int i=0; int _n=0;
while(i<=n-1){
int j=i+1; LL cnt=a[i].Fir;
while(j<=n&&a[i].Sec==a[j].Sec) cnt+=a[j++].Fir;
a[_n++]=mp(cnt,a[i].Sec);
i=j;
}
n=_n;
}
int fail[maxn];
void make_kmp(){
for(int i=2,j=0;i<=m-2;i++){
while(j&&b[j+1]!=b[i]) j=fail[j];
if(b[j+1]==b[i]) j++;
fail[i]=j;
}
}
void kmp(){
for(int i=0,j=0;i<=n-1;i++){
while(j&&b[j+1]!=a[i]) j=fail[j];
if(b[j+1]==a[i]) j++;
if(j==m-2){
if(a[i+1].Sec==b[m-1].Sec&&a[i+1].Fir>=b[m-1].Fir&&a[i-m+2].Sec==b[0].Sec&&a[i-m+2].Fir>=b[0].Fir) ans++;
j=fail[j];
}
}
}
int main(){
freopen("cf631D.in","r",stdin);
freopen("cf631D.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=0;i<=n-1;i++) scanf("%d-%c",&a[i].Fir,&a[i].Sec);
for(int i=0;i<=m-1;i++) scanf("%d-%c",&b[i].Fir,&b[i].Sec);
Pre(a,n); Pre(b,m);
if(n<m) return printf("0"),0;
if(m==1){
ans=0;
for(int i=0;i<=n-1;i++) if(a[i].Sec==b[0].Sec&&a[i].Fir>=b[0].Fir) ans+=a[i].Fir-b[0].Fir+1;
printf("%I64d\n",ans);
return 0;
}
if(m==2){
ans=0;
for(int i=0;i<=n-2;i++)
if(a[i].Sec==b[0].Sec&&a[i].Fir>=b[0].Fir&&a[i+1].Sec==b[1].Sec&&a[i+1].Fir>=b[1].Fir) ans++;
printf("%I64d\n",ans);
return 0;
}
make_kmp();
kmp();
printf("%I64d\n",ans);
return 0;
}