Codeforces 631D - Messenger KMP
题目:http://codeforces.com/problemset/problem/631/D
题意:
输入一段压缩后的字符串,问子串在主串中出现的次数
分析:
KMP匹配求子串在主串中出现的次数,因为是压缩后的字符串,这就要考虑字符串的长度。因为要完全匹配,显然,模式串的中间的字符和数目必须要完全和主串匹配,但是前后两个字符数目可以不相等,所以模式串删去前后两个字符,去和主串匹配,完全匹配时,在比较前后两个字符是否主串中相应位置的字符匹配。删去前后两个字符前,要判断模式串长度:
如果模式串长度是1,那么直接在主串中找对应的字符,比较长度,如果模式串长度是2,那么也是直接在主串中找模式串,比较字符一样,并且主串中字符数目均不小于模式串中字符数目。然后剩下的就用KMP匹配就好。
#include<iostream>
#include<cstdio>
using namespace std;
#define fi first
#define se second
#define mp make_pair
typedef long long ll;
typedef pair<char,ll>pii;
const int N=2e5+5;
pii s[N],t[N],t0,tt;
int next[N],tlen,slen;
void getNext()
{
int i,j;
i=0;j=next[0]=-1;
while(i<tlen){
if(j==-1||t[i]==t[j])next[++i]=++j;
else j=next[j];
}
}
ll KMP_Count()
{
ll ans=0;
getNext();
int j=0;
for(int i=1;i<slen;i++){
while(j>0&&s[i]!=t[j])j=next[j];
if(s[i]==t[j])j++;
if(j==tlen){
if(t0.fi==s[i-tlen].fi&&t0.se<=s[i-tlen].se
&&tt.fi==s[i+1].fi&&tt.se<=s[i+1].se)ans++;
j=next[j];
}
}
return ans;
}
int main()
{
int n,m;
//freopen("f.txt","r",stdin);
scanf("%d%d",&n,&m);
char ci;
ll li;
scanf("%I64d-%c",&s[0].se,&s[0].fi);
n--; slen=1;
while(n--){
scanf("%I64d-%c",&li,&ci);
if(s[slen-1].fi==ci){
s[slen-1].se+=li;
}
else s[slen++]=mp(ci,li);
}
scanf("%I64d-%c",&t[0].se,&t[0].fi);
//cout<<t[0].fi<<' '<<t[0].se<<endl;
m--; tlen=1;
while(m--){
scanf("%I64d-%c",&li,&ci);
if(t[tlen-1].fi==ci){
t[tlen-1].se+=li;
}
else t[tlen++]=mp(ci,li);
}
if(tlen==1){
ll ans=0;
for(int i=0;i<slen;i++){
if(t[0].fi==s[i].fi&&t[0].se<=s[i].se)ans+=s[i].se-t[0].se+1;
}
cout<<ans<<endl;return 0;
}
if(tlen==2){
ll ans=0;
for(int i=1;i<slen;i++){
if(t[0].fi==s[i-1].fi&&t[1].fi==s[i].fi
&&t[0].se<=s[i-1].se&&t[1].se<=s[i].se){
ans++;
}
}
cout<<ans<<endl;return 0;
}
t0=t[0];tt=t[tlen-1];
for(int i=0;i<tlen-1;i++)
t[i]=t[i+1];
tlen-=2;
cout<<KMP_Count()<<endl;
return 0;
}
Input
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 200 000) — the number of blocks in the strings t and s, respectively.
The second line contains the descriptions of n parts of string t in the format “li-ci” (1 ≤ li ≤ 1 000 000) — the length of the i-th part and the corresponding lowercase English letter.
The second line contains the descriptions of m parts of string s in the format “li-ci” (1 ≤ li ≤ 1 000 000) — the length of the i-th part and the corresponding lowercase English letter.
Output
Print a single integer — the number of occurrences of s in t.
Examples
Input
5 3
3-a 2-b 4-c 3-a 2-c
2-a 2-b 1-c
Output
1