• 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
    ", ans);
    }
    
    
  • 相关阅读:
    JavaScript 将行结构数据转化为树结构数据源(高效转化方案)
    转—记录一下获取NC程序名称的方法
    选择对象单开图层
    找体的顶平面
    关闭当前工作部件
    对同一高度的体着色
    NX二次开发,对象上色
    隐藏同色对象
    线性移动更新
    NX 二次开发,线性移动uf5943
  • 原文地址:https://www.cnblogs.com/macinchang/p/5412547.html
Copyright © 2020-2023  润新知