Codeforces 631D Messenger KMP

链接

Codeforces 631D Messenger

题意

a-b表示有a个字符b。 用这样的表示方式给出主串和模式串,问模式串在主串中出现了多少次。

思路

非常明显的KMP了,这里只要匹配去掉两端的模式串,端点单独匹配就好了。

代码

#include <bits/stdc++.h>

#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN 200005
using namespace std;

struct node{
	LL num;
	char ch;
	node(LL x = 0, char y = 0) :num(x), ch(y){};
	bool operator <= (const node &b)const{
		return ch == b.ch && num <= b.num;
	}
	bool operator == (const node &b)const{
		return ch == b.ch && num == b.num;
	}
};
node a[MAXN], b[MAXN];
int last[MAXN];
int res[MAXN];
void work(char *s, LL &x, char &ch){
	x = 0;
	int p = 0;
	while (s[p] != '-'){
		x = x * 10 + s[p] - '0';
		++p;
	}
	ch = s[p + 1];
}
int n, m;
int main(){
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
	scanf("%d%d", &n, &m);
	int p = 0;
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	char s[30];
	LL x;
	char ch;
	for (int i = 1; i <= n; ++i){
		scanf("%s", s);
		work(s, x, ch);
		if (p == 0 || ch != a[p].ch){
			a[++p] = node(x, ch);
		}
		else{
			a[p].num += x;
		}
	}
	n = p;
	p = 0;
	for (int i = 1; i <= m; ++i){
		scanf("%s", s);
		work(s, x, ch);
		if (p == 0 || ch != b[p].ch){
			b[++p] = node(x, ch);
		}
		else{
			b[p].num += x;
		}
	}
	m = p;
	last[2] = 1;
	x = 1;
	for (int i = 3; i <= m - 1; ++i){
		while (b[x + 1].ch != b[i].ch && x > 1){
			x = last[x];
		}
		if (b[x + 1].ch == b[i].ch){
			++x;
		}
		last[i] = x;
	}
	LL ans = 0;
	if (m > 2){
		x = 1;
		int cnt = 0;
		for (int i = 2; i < n; ++i){
			while (x > 1 && (!(a[i] == b[x + 1]))){
				x = last[x];
			}
			if (a[i] == b[x + 1]){
				++x;
			}
			if (x == m - 1){
				if (b[1] <= a[i - m + 2] && b[m] <= a[i + 1]){
					++ans;
				}
				x = last[x];
			}
		}
	}
	if (m <= 2){
		for (int i = 1; i <= n; ++i){
			if (b[1] <= a[i] && b[m] <= a[i + m - 1]){
				if (m == 1){
					ans += a[i].num - b[1].num + 1;
				}
				else{
					++ans;
				}
			}
		}
	}
	printf("%I64d\n", ans);
}

posted on 2016-04-20 14:25  张济  阅读(204)  评论(0编辑  收藏  举报

导航