您的位置:首页 > 其它

Codeforces Round #344 (Div. 2) D. Messenger(kmp)

2016-07-13 13:49 393 查看
题目链接:点这里!!!!

题意:

给你两个字符串a,b,求b在a中出现的次数。

字符串出现的形式为a1-c1 a2-c2 a3-c3 ... an-cn(b字符串为m)。ai-ci表示ci这个字符连续出现了ai次。

比如:3-a 2-b 2-a 3-d 是aaabbaaddd。

取值范围:m,n<=200000, ai<=1e6

题解:

1、如果出现3-a 7-a这种相邻两个的字符是一样的,先合并掉。

2、m==1我们直接去找a中哪一块的字符为与b中的相等,然后去判个数就可以了。

3、m==2我们考虑a中相邻的两个字符是否与b中的两个相等,再判下每个块的大小关系就可以了。

4、m>2 去掉b的头部和尾部,直接去a中跑kmp就可以了。如果匹配到了的话,再判下两头是否符合条件就可以了。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define LL long long
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
#pragma comment(linker, "/STACK:102400000000,102400000000")
const LL MOD = 1000000007;
const int N = 2e5+15;
const int maxn = 8e3+15;
const int letter = 130;
const LL INF = 1e7;
const double pi=acos(-1.0);
const double eps=1e-10;
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,f
;
LL ans=0;
struct node{
LL v;
char c;
bool operator ==(const node &p)const {
return v==p.v&&c==p.c;
}
}a
,b
,p
;
void getf(node a[],int n){
f[0]=f[1]=0;
int j=0;
for(int i=1;i<n;i++){
j=f[i];
while(j&&!(a[i]==a[j])) j=f[j];
if(a[i]==a[j]) f[i+1]=j+1;
else f[i+1]=0;
}
}
void kmp(node a[],node b[]){
for(int i=1;i<m-1;i++) p[i-1]=b[i];
getf(p,m-2);
int vs=m-2;
for(int i=1,j=0;i<n-1;i++){
if(j==vs) j=f[j];
while(j&&!(a[i]==p[j]))j=f[j];
if(a[i]==p[j])j++;
if(j==vs){
if(b[0].c==a[i-vs].c&&b[0].v<=a[i-vs].v&&b[m-1].c==a[i+1].c&&b[m-1].v<=a[i+1].v)ans++;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%I64d-%c",&a[i].v,&a[i].c);
for(int i=0;i<m;i++) scanf("%I64d-%c",&b[i].v,&b[i].c);
int cnt=0;
for(int i=1;i<n;i++){
if(a[i].c!=a[i-1].c) a[++cnt]=a[i];
else a[cnt].v+=a[i].v;
}
n=cnt+1;
cnt=0;
for(int i=1;i<m;i++){
if(b[i].c!=b[i-1].c) b[++cnt]=b[i];
else b[cnt].v+=b[i].v;
}
m=cnt+1;
if(m==1){
for(int i=0;i<n;i++){
if(a[i].c==b[0].c&&a[i].v>=b[0].v) ans+=a[i].v-b[0].v+1;
}
}
else if(m==2){
for(int i=0;i<n-1;i++){
if(a[i].c==b[0].c&&a[i+1].c==b[1].c&&a[i].v>=b[0].v&&a[i+1].v>=b[1].v)ans++;
}
}
else {
kmp(a,b);
}
printf("%I64d\n",ans);
return 0;
}
/**
10 8
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
**/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  kmp