2017西安交大ACM小学期 神器插座 KMP匹配

神奇插座

发布时间: 2017年7月3日 11:27   最后更新: 2017年7月5日 13:46   时间限制: 500ms   内存限制: 128M

AA所在的国家有一项神奇的发明:插座。这里的插座不仅有两孔、三孔,而是有多种形态,下面用不同的小写字母表示不同的插座。插线板可以看做一排插座,因而下面用小写字母组成的字符串表示插线板。

该国家的用电器的插头也很特别,是由一串插头固定在一起的,下面用大写字母组成的字符串表示。只有插座和插头匹配,该用电器才能插在插线板上。例如:

插头ABCBA可以插在插线板abcbabcba上。

现在问题来了:给定插线板和插头,问该插线板上最多能插几个这样的插头?注意,这些插头不能重叠。

多组测试数据。
每组测试数据包含两行,第一行为插座,第二行为插头。
插座、插头对应的字符均不超过 106
总数据量不超过 107 个字符。

对每组数据,输出一行一个整数,表示答案。

  复制
abcbabcba
ABCBA
1
解法非常简单,直接进行KMP匹配就可以了,但是KMP的模板要有一个小小的改动(因为这里题目要求插头不能重叠),那就是只要匹配到一个插头以后,直接置j = 0

这样可以避过重叠

代码:

#include <iostream>
#include <cstdio>
using namespace std; 
#define MAXN 2000001
char s[MAXN];
char str[MAXN];
int fail[MAXN];
int search(char *str)
{
  int ans = 0;
  for (int i = 0, j = 0; str[i]; i++){
    while (j && str[i] - 'a' != s[j] - 'A')j = fail[j - 1];
    if (str[i] - 'a' == s[j] - 'A' && !s[++j]){ans++;j=0;}
  }
  return ans;
}

void make_fail()
{
  for (int i = 1, j = 0; s[i]; i++){
    while (j && s[i] != s[j])j = fail[j - 1];
    if (s[i] == s[j])fail[i] = ++j;
    else fail[i] = 0;
  }
}
int main(){
	while(~scanf("%s %s",str,s)){
		make_fail();
		printf("%d\n",search(str));
	}
	
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值