hdu5918-kmp|队列模拟- Sequence I

https://vjudge.net/problem/HDU-5918
题意:给定两个序列,一个为主串,一个为模式串,问主串中 间隔长度为p一个一个取构成了p个子串,问你包含模式串的数量有多少个。。
思路:事后看来,直接kmp就行。。就是把那么多子串取出来而已。然后用一下kmp的板子。。这简直是模拟题。。。
当时我的想法就是把等于模式串的第一个数入队列,然后用优先队列一个一个找。后来发现直接用队列就行。。因为处理顺序是一定的。。,优先队列反而有点多余。。。
*:kmp那个数组用next这个名字,会ce。。

  #include <bits/stdc++.h>
using namespace std;
/* 用kmp枚举起点也行,

*/
const int maxn = 1e6+2000;
int nex[maxn];
int S[maxn],T[maxn];
int slen, tlen;
void getNext()
{
    int j, k;
    j = 0; k = -1; nex[0] = -1;
    while(j < tlen)
        if(k == -1 || T[j] == T[k])
            nex[++j] = ++k;
        else
            k = nex[k];
            //for(int i=0;i<tlen;i++)
                //cout<<next[i]<<" "<<endl;

}
/*
返回模式串T在主串S中首次出现的位置
返回的位置是从0开始的。
*/
int KMP_Index()
{
    int i = 0, j = 0;
    getNext();
    while(i < slen && j < tlen)
    {
        if(j == -1 || S[i] == T[j])
        {
            i++; j++;
        }
        else
            j = nex[j];
    }
    if(j == tlen)
        return i - tlen;
    else
        return -1;
}
/*
返回模式串在主串S中出现的次数
*/
int KMP_Count()
{
    /*for(int i=0;i<slen;i++){
        cout<<S[i]<<" ";
    }
    cout<<endl;
    cout<<"!!!"<<tlen<<endl;
    for(int i=0;i<tlen;i++){
        cout<<T[i]<<" ";
    }
    //cout<<endl;*/
    int ans = 0;
    int i, j = 0;
    if(slen == 1 && tlen == 1)
    {
        if(S[0] == T[0])
            return 1;
        else
            return 0;
    }
    getNext();
    for(i = 0; i < slen; i++)
    {
        while(j > 0 && S[i] != T[j])
            j = nex[j];
        if(S[i] == T[j])
            j++;
        if(j == tlen)
        {
            ans++;
            j = nex[j];
        }
    }
    return ans;
}
int ori[maxn];
int main()
{   int t;
    int m,n,p;
    int cas=1;
    scanf("%d",&t);
    while(t--){
          scanf("%d%d%d",&m,&n,&p);
           for(int i=0;i<m;i++){
               scanf("%d",&ori[i]);
               }
           for(int i=0;i<n;i++){
               scanf("%d",&T[i]);
           }
           //cout<<ori<<"**"<<T<<endl;
           tlen=n;
           int length=m;
           int ans=0;
           for(int i=0;i<p;i++){
               int len2=0;
               for(int j=i;j<length;j+=p){
                  S[len2++]=ori[j];
                  //cout<<ori[j]<<" ";
               }
               //cout<<endl;
               if(len2<tlen) continue;
               slen=len2;
               ans+=KMP_Count();
           }
           printf("Case #%d: %d\n",cas++,ans);
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+700;
int a[maxn];
int b[maxn];
struct Node {
   int num;
   int loc;
   int siz;
   Node(int _a,int _b,int _c){
       num=_a;
       loc=_b;
       siz=_c;
   }
   friend bool operator < (Node a, Node b)
   {
       return a.loc>b.loc;    //x小的优先级高。
   }
};
priority_queue<Node>q;
int main()
{     int t;
    int m,n,p;
      scanf("%d",&t);
      int cas=1;
    while(t--){
          int sum=0;
          scanf("%d%d%d",&m,&n,&p);
          //getchar();
          for(int i=1;i<=m;i++){
              scanf("%d",&a[i]);
          }
          for(int i=1;i<=n;i++){
               scanf("%d",&b[i]);
          }
           while(!q.empty())
               q.pop();
          for(int i=1;i<=m;i++){
              if(a[i]==b[1]){
                 q.push(Node(b[1],1,i));
                 //cout<<i<<" "<<endl;
                 }
          }
          while(!q.empty()){
                Node s=q.top();
                 q.pop();
                 if(s.loc==n){
                     sum++;continue;
                 }
                 if(s.siz+p<=m&&a[s.siz+p]==b[s.loc+1]){
                    q.push(Node(b[s.loc+1],s.loc+1,s.siz+p));
                   //cout<<s.siz+p<<" "<<endl;
                 }
          }
          printf("Case #%d: %d\n",cas++,sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值