ZOJ KMP例题 —3643Keep Deleting & 3954Knuth-Morris-Pratt Algorithm

  • 例题1 3954Knuth-Morris-Pratt Algorithm

    KMP

    Knuth-Morris-Pratt Algorithm
    Time Limit: 1000 msMemory Limit: 65536 KB
    In computer science, the Knuth-Morris-Pratt string searching algorithm (or KMP algorithm) searches for occurrences of a "word" W within a main "text string" S by employing the observation that when a mismatch occurs, the word itself embodies sufficient information to determine where the next match could begin, thus bypassing re-examination of previously matched characters.
    ​
    Edward is a fan of mathematics. He just learnt the Knuth-Morris-Pratt algorithm and decides to give the following problem a try:
    ​
    Find the total number of occurrence of the strings "cat" and "dog" in a given string s.
    ​
    As Edward is not familiar with the KMP algorithm, he turns to you for help. Can you help Edward to solve this problem?
    ​
    Input
    There are multiple test cases. The first line of input contains an integer T (1 ≤ T ≤ 30), indicating the number of test cases. For each test case:
    ​
    The first line contains a string s (1 ≤ |s| ≤ 1000).
    ​
    Output
    For each case, you should output one integer, indicating the total number of occurrence of "cat" and "dog" in the string.
    ​
    Sample Input
    7
    catcatcatdogggy
    docadosfascat
    dogdddcat
    catcatcatcatccat
    dogdogdogddddooog
    dcoagtcat
    doogdog
    Sample Output
    4
    1
    2
    5
    3
    1
    1
    Hint
    For the first test case, there are 3 "cat" and 1 "dog" in the string, so the answer is 4.
    ​
    For the second test case, there is only 1 "cat" and no "dog" in the string, so the answer is 1.

#include<stdio.h>
#include<string.h>
char s[1009];
int ls;
int kmp(char a[])
{
     int i,j,ans=0;
     for(i=1,j=0;i<=ls;i++)
     {
          while(j&&a[j+1]!=s[i])j=0;
         if(a[j+1]==s[i])j++;
          if(j==3)
          {
               ans++;
          }
     }
     return ans;
}
int main()
{
     int t,i,j;
     char a[5]={" cat"},b[5]={" dog"};
     scanf("%d",&t);
     while(t--)
     {
          scanf("%s",s+1);
          ls=strlen(s+1);
          int ans=kmp(a)+kmp(b);
          printf("%d\n",ans);
     }
     return 0;
}

  • 例题2 Keep Deleting

    KMP+堆栈

    Keep Deleting
    Time Limit: 2000 msMemory Limit: 65536 KB
    Assume that string A is the substring of string B if and only if we can find A in B, now we have a string A and another string B, your task is to find a A in B from B's left side to B's right side, and delete it from B till A is not a substring of B, then output the number of times you do the delete.
    ​
    There are only letters(A-Z, a-z) in string A and B.
    ​
    Input
    This problem contains multiple test cases. Each case contains two line, the first line is string A, the second line is string B, the length of A is less than 256, the length of B is less than 512000.
    ​
    Output
    Print exactly one line with the number of times you do the delete for each test case.
    ​
    Sample Input
    abcd
    abcabcddabcdababcdcd
    Sample Output
    5
    Hint
    abcabcddabcdababcdcd delete=0
    abcdabcdababcdcd     delete=1
    abcdababcdcd         delete=2
    ababcdcd             delete=3
    abcd                 delete=4
                         delete=5

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
using namespace std;
#define N 512009
char a[260],b[N];
int ne[N];
int main()
{
     int i,j;
     while(~scanf("%s%s",a+1,b+1))
     {
          int ans=0;
          stack<int>s; 
          int la=strlen(a+1),lb=strlen(b+1);
          memset(ne,0,sizeof(ne));//clear ne[]
          //ne[]
          for(i=2,j=0;i<=la;i++)
          {
               while(j&&a[i]!=a[j+1])j=ne[j];
               if(a[i]==a[j+1])j++;
               ne[i]=j;
          }
          for(i=1,j=0;i<=lb;i++)
          {
               while(j&&a[j+1]!=b[i])j=ne[j];
               if(b[i]==a[j+1])j++;
               s.push(j);
               if(j==la)
               {
                    ans++;
                    for(int t=0;t<la;t++)
                    {
                         s.pop();//delete the found substring
                    }
                    if(!s.empty())
                    {
                         j=s.top();
                    }
                    else
                    {
                         j=0;
                    }
                } 
          }
          printf("%d\n",ans);
     }
     return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值