CF631D Messenger(KMP)
作者:互联网
虽然是块,但是其实可以看作是除了两边的两块外,中间做一下kmp算法
但是有几个坑点:
1.相同的数字要合并,因为相同的数字代表的其实是同一种,如果不合并,在匹配的时候看上去是不一样的
2.对于块数为1和2的直接特判一下就好
3.对于中间匹配的,也不要忘记判断一下两边的块是否合理
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> pll; const int N=5e5+10; const int inf=0x3f3f3f3f; const ll mod=998244353; struct node{ ll l; char c; }a[N],b[N]; int n,m; int nxt[N]; void get(node *a,int &n){ int m=0; for(int i=0;i<n;++i) { if(m==0 || a[m-1].c!=a[i].c) a[m++]=a[i]; else a[m-1].l+=a[i].l; } n=m; } void get_nxt(){ nxt[1]=0; int i; int j; for(i=2,j=0;i<m-1;i++){ while(j&&!(b[j+1].l==b[i].l&&b[j+1].c==b[i].c)) j=nxt[j]; if((b[j+1].l==b[i].l&&b[j+1].c==b[i].c)) j++; nxt[i]=j; } } ll solve(){ get_nxt(); int i,j; ll ans=0; for(i=0,j=0;i<n;i++){ while(j&&!((b[j+1].l==a[i].l&&b[j+1].c==a[i].c))) j=nxt[j]; if(b[j+1].l==a[i].l&&b[j+1].c==a[i].c) j++; if(j==m-2){ if(a[i+1].c==b[m-1].c&&a[i+1].l>=b[m-1].l&&a[i-m+2].c==b[0].c&&a[i-m+2].l>=b[0].l) ans++; j=nxt[j]; } } return ans; } int main(){ //ios::sync_with_stdio(false); scanf("%d%d",&n,&m); for(int i=0;i<n;++i)scanf("%lld-%c",&a[i].l,&a[i].c); for(int i=0;i<m;++i)scanf("%lld-%c",&b[i].l,&b[i].c); get(a,n); get(b,m); if(m==1){ ll ans=0; int i; for(i=0;i<n;i++){ if(a[i].c==b[0].c&&a[i].l>=b[0].l){ ans+=a[i].l-b[0].l+1; } } cout<<ans<<endl; } else if(m==2){ ll ans=0; for(int i=0;i<n-1;i++){ if(a[i].c==b[0].c&&a[i].l>=b[0].l&&a[i+1].c==b[1].c&&a[i+1].l>=b[1].l) ans++; } cout<<ans<<endl; } else{ cout<<solve()<<endl; } return 0; }View Code
标签:typedef,CF631D,int,ll,KMP,long,Messenger,&&,ans 来源: https://www.cnblogs.com/ctyakwf/p/13592365.html