• kmp


    KMP cekmp

    例题 HDU 1711 Number Sequence

    题目分析 : KMP 模板题

    kmp主要 依靠于 next[]数组查找进行优化(前后缀 最长公共子串长度)
    如何 优化的呢在查找的时候 在某一处匹配失败时可以直接通过 next[]数组进行跳转
    不用重头匹配 简化了查询步骤;
    比如 : (ABCAB AABB) ( ABCAB CSDFDS)
    当ABCA匹配成功而 ABCA B 匹配失败时 通过next数组就可以
    直接跳转到AB(C)位置进行比较
    代码如下:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector> 
    using namespace std;
    int ss[1000005],s[10005];//创建数字存储数组 
    int mo[10005];//next[]数组(最长公共前后缀长度)
    int n,m;
    int kmp() 
    {
    //next[]数组求值
    	int j=1,k=0; //j为前缀坐标,k为后缀坐标
    	mo[1]=0;//一个数字时 最长公共前后缀为0
    	while(j<=m) //坐标要求不大于最大长度
    	{
    		if(k==0||s[j]==s[k])//k=0是空状态 当前后缀一样市 
    		{
    			j++;//前缀坐标后移
    			k++;//后缀坐标后移
    			mo[j]=k;//最长公共前后缀 赋值
    		}
    		else
    		k=mo[k];//如果 不相等  就跳转到 next[] --->缩短路径(可以这么说吧)
    	}
    	//比较
    	int i=1,j=1;//初始比较坐标赋值 
    	while(i<=n)//最大坐标不大于 最长所给
    	{
    		if(j==0||ss[i]==s[j])//j=0代表 没有部分前缀相等 //相等就往后移动 
    		{
    			i++;
    			j++;
    		}
    		else
              j=mo[j];//否则就跳转 到next[] 
            if(j==m+1)//当有匹配最后一个成功时 会出现 j++所以有j==m+1
              {
              	return i-m;//(j++)-m==j-m+1
    		  }
    	}
    	return -1;
    }
    int main() 
    {
    int t;
    cin>>t;
    while(t--)
    {
    	scanf("%d %d",&n,&m);	
    	for(int i=1;i<=n;i++)//**注意 输入时是从1开始 将0位置空出来了
    	scanf("%d",&ss[i]);
    	
    	for(int j=1;j<=m;j++)//**注意 输入时是从1开始 将0位置空出来了
    	scanf("%d",&s[j]);
    	 cout<<kmp()<<endl;
    }
    	return 0;
    }
    

    例题 POJ 1961 Period

    解题思路: 就是kmp里的求next数组 然后依次扫一遍看是否出现循环节

    AC代码如下:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int maxn=1000000+10;
    int next[maxn];
    string str;
    int main()
    {
      int n;
      int ans=0;
      while(cin>>n&&n)
      {
      	ans++;
      	cin>>str;
      	next[0]=next[1]=0;
      	for(int i=1;i<n;i++)
     {
     	int j=next[i];
     	while(j&&str[i]!=str[j])
     	j=next[j];
        next[i+1]=(str[i]==str[j])?j+1:0;
     }
     cout<<"Test case #"<<ans<<endl;
         for(int i=2;i<=n;i++)
         {
         	int len=i-next[i];
         	if(next[i]>0&&!(i%len))
         	cout<<i<<" "<<i/len<<endl;
    	 }
    	 cout<<endl;
      }
    		return 0;
    }
    
  • 相关阅读:
    Mybatis各种模糊查询
    ORACLE查询当前资产状态,和另一个数据库联查,(查询重复数据中第一条),子查询作为字段查询
    驱动文件操作
    驱动开发中使用安全字符串函数
    驱动开发 判断内存是否可读 可写
    驱动模式使用__try __excpet
    简单解释Windows如何使用FS段寄存器
    手动载入NT驱动
    PUSHA/PUSHAD
    跳转指令公式计算 HOOK
  • 原文地址:https://www.cnblogs.com/maxv/p/11478233.html
Copyright © 2020-2023  润新知