hdu1711 + hdu1686 + hdu2087 kmp入门

I am coming!KMP!

(中二完毕)

 

 

1711:

建议数组用pre命名而不是next,next是c++的关键字

问一个串是否在另一个串中出现过,如出现输出最小出现位置,上模板

--

复制代码
#include <iostream>
#include <math.h>
#include <string.h>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <algorithm>
#include <cstdio>
using namespace std;
int pre[1000009],t[1000009],s[1000009];
int main()
{
    
    
    int T,n,m;
    cin>>T;
    
    while(T--)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            cin>>t[i];
        }
        
        for(int i=1;i<=m;i++)
        {
            cin>>s[i];
        }
        
        pre[0]=0;
        pre[1]=0;
        
        int k=0;
        for(int i=2;i<=m;i++)
        {
            while(k&&s[i]!=s[k+1]) k=pre[k];
            if(s[i]==s[k+1]) k++;
            pre[i]=k;
        }
        
    
        
        
        int ok=1;
        k=0;
        for(int i=1;ok&&i<=n;i++)
        {
            while(k&&t[i]!=s[k+1]) 
            {
              k=pre[k];    
            }
            
            if(t[i]==s[k+1]) k++;
            
            if(k==m)
            {   ok=0;
                printf("%d\n",i-m+1);
            }
            
        //    cout<<i<<" "<<k<<endl;
        }
        if(ok) cout<<-ok<<endl;
    }
}
复制代码

 

 

hdu 1686

问s串是否在t串中出现过,求次数,允许重叠。

每次k能匹配到strlen(s)时,num++即可;

复制代码
#include <iostream>
#include <math.h>
#include <string.h>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <algorithm>
#include <cstdio>
using namespace std;
int pre[1000009];
char s[1000009],t[1000009];
int main()
{
    

    
    int T,n,m;
    scanf("%d",&T);
    
    while(T--)
    {
    
          scanf("%s",s+1);
        scanf("%s",t+1);
        
        pre[0]=0;
        pre[1]=0;
        
        int k=0;
        for(int i=2;i<=strlen(s+1);i++)
        {
            while(k&&s[i]!=s[k+1]) k=pre[k];
            if(s[i]==s[k+1]) k++;
            pre[i]=k;
        }

        k=0;
        int num=0;
        
        for(int i=1;i<=strlen(t+1);i++)
        {
            while(k&&t[i]!=s[k+1])   k=pre[k];    
        
            
            if(t[i]==s[k+1]) k++;
            
            if(k==strlen(s+1)) num++;
        //    cout<<i<<" "<<k<<endl;
        }
       printf("%d\n",num);
    }
}
复制代码

 

--

 

hdu   2087

同上,问出现次数,但不同的是不允许重叠,记录每次出现的位置,最后统计答案时声明一指针,如果ans[i]的起点仍在该指针管辖范围内,就不统计,否则令指针=i,保证不重叠。

虽然说狠狠地暴力一通也能过啦。

复制代码

#include <iostream> #include <math.h> #include <string.h> #include <vector> #include <map> #include <queue> #include <stdio.h> #include <algorithm> #include <cstdio> using namespace std; int pre[1000009],ans[1000009]; char s[1000009],t[1000009]; int main() { int T,n,m; while(1) { scanf("%s%s",t+1,s+1); if(t[1]=='#') break; pre[0]=0; pre[1]=0; int k=0; for(int i=2;i<=strlen(s+1);i++) { while(k&&s[i]!=s[k+1]) k=pre[k]; if(s[i]==s[k+1]) k++; pre[i]=k; } k=0; int num=0; for(int i=1;i<=strlen(t+1);i++) { while(k&&t[i]!=s[k+1]) k=pre[k]; if(t[i]==s[k+1]) k++; if(k==strlen(s+1)) { num++; ans[num]=i-strlen(s+1)+1; } } if(num==0) { printf("0\n"); continue; } int j=1,cnt=1; for(int i=2;i<=num;i++) { if(ans[i]<=ans[j]+strlen(s+1)-1) continue; cnt++; j=i; } printf("%d\n",cnt); } }
复制代码

 

posted @   liyishui  阅读(303)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示