KMP板题(HDU - 2087 和 HDU - 1686 )

这两个道题其实差不多,只不过一个允许选的字符有交叉,一个不允许。就是AZAZA中石油2个AZA还是有1个AZA的差别。

HDU - 2087

   题目链接

题目大意:

        给定文本串T和匹配串S,问你文本串里有几个匹配串,其中字符不能有交叉。比如AZAZA里面只有一个AZA。

题目思路:

       只需要把板子改动一个地方,当我们找到匹配的第一个地方的时候不要跳出来,而是把匹配串重新归零从第一位重新匹配就好了。

附代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1005

using namespace std;
char s[maxn],t[maxn];
int nxt[maxn];
int ans;
int n,m;

void build()
{
     int k=0;
     nxt[0]=0;
     for(int i=1;i<m;i++)
     {
          while(k&&t[i]!=t[k])
               k=nxt[k-1];
          if(t[i]==t[k])
               k++;
          nxt[i]=k;
     }
}
void kmp()
{
     int j=0;
     for(int i=0;i<n;i++)
     {
          while(j&&s[i]!=t[j])
               j=nxt[j-1];
          if(s[i]==t[j])
               j++;
          if(j==m)//前面j++
          {
               ans++;
               j=0;//加上这里即可
          }
               //return i-m+1;
     }
     //return -2;
}
int main(void)
{
     while(~scanf("%s",s))
     {
          ans=0;
          if(s[0]=='#')
               break;
          scanf("%s",t);
          n=strlen(s);
          m=strlen(t);
          build();
          kmp();
          printf("%d\n",ans);
     }
     return 0;
}

---------------------------------------------------------------我是一个分割线o_o----------------------------------------------------------------------

HDU - 1686

      题目链接

题目大意:

跟上一题差不多,只不过允许有交叉

题目思路:

如果允许有交叉,显然我们在这一位匹配结束了之后,把j回退到 nxt[ j ] 的位置继续比对就好了呀

附代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1000005

using namespace std;
typedef long long ll;
char s[maxn],t[maxn];
ll nxt[maxn];
int n,m;
int ans;

void build()
{
     int k=0;
     nxt[0]=0;
     for(int i=1;i<m;i++)
     {
          while(k&&t[i]!=t[k])
               k=nxt[k-1];
          if(t[i]==t[k])
               k++;
          nxt[i]=k;
     }
}
void kmp()
{
     int j=0;
     for(int i=0;i<n;i++)
     {
          while(j&&s[i]!=t[j])
               j=nxt[j-1];
          if(s[i]==t[j])
               j++;
          if(j==m)//前面j++
          {
               ans++;
               j=nxt[j-1];//这里这里
          }
               //return i-m+1;
     }
     //return -2;
}
int main(void)
{
     int tt;
     scanf("%d",&tt);
     while(tt--)
     {
          ans=0;
          memset(nxt,0,sizeof(nxt));
          scanf("%s%s",t,s);
          n=strlen(s);
          m=strlen(t);
          build();
          kmp();
          printf("%d\n",ans);
     }
}

/*
3
AZA
AZAZAZA
*/

呼呼

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值