每天都在憧憬这些算法我都懂了的那一天。。。然鹅,KMP又看了一遍还是觉得稀里糊涂的。先放个模板题好了(;′⌒`)


【hdu1711】 Number Sequence

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 41364    Accepted Submission(s): 17113

Problem Description

Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], ...... , a[K + M - 1] = b[M]. If there are more than one K exist, output the smallest one.

Input

The first line of input is a number T which indicate the number of cases. Each case contains three lines. The first line is two numbers N and M (1 <= M <= 10000, 1 <= N <= 1000000). The second line contains N integers which indicate a[1], a[2], ...... , a[N]. The third line contains M integers which indicate b[1], b[2], ...... , b[M]. All integers are in the range of [-1000000, 1000000].

Output

For each test case, you should output one line which only contain K described above. If no such K exists, output -1 instead.

Sample Input

2
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 2 1

Sample Output

6

-1

Source

HDU 2007-Spring Programming Contest

【分析】 模板题

【代码】参考--

#include<iostream>
#include<cstdio>
#define maxn 1e6+5
int s[maxn],p[maxn],next[maxn];
int m,n;
void getnext()
{int j=0,k=-1;next[0]=-1;while(j<m){if(k==-1||p[j]==p[k]){j++;k++;next[j]=k;}else k=next[k];}
}
int kmp()
{int i=0,j=0;getnext();while(i<n){if(j==-1||s[i]==p[j]){i++;j++;}else j=next[j];if(j==m)return i;}return -1;
}
int main()
{int t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=0;i<n;i++)scanf("%d",&s[i]);for(int i=0;i<m;i++)scanf("%d",&p[i]);if(kmp()==-1)printf("-1\n");else printf("%d\n",kmp()-m+1);}return 0;
}

下面是关于next数组的一些:KMP算法 —— next 数组的应用 --- 前缀中最小循环节,最大重复次数

在KMP算法的使用中,首要任务就是获取一个字符串的next数组,所以我们得明白next数组的含义(最好的方法是自己弄个例子,在草稿纸上模拟一下),在这里,通俗一点讲,next[k] 表示,在模式串的 k 个字符失配了,然后下一次匹配从 next[k] 开始(next[k] 中保存的是该失配字符的前一个字符在前面出现过的最近一次失配的字符后面的一个字符的位置,有点绕口,自己写个例子看看就明白了,也可以继续往下看,有介绍,然后再自己尝试写写 )。

至于next数组为什么可以用来求重复前缀呢,而且求出来的重复前缀是最小的呢?

next数组的求法:

void getnext(int len)
{ int i=0,j=-1; next[0]=-1; while(i<len){ if(j==-1 || str[i]==str[j])    { i++;j++; next[i]=j; }else j=next[j]; }}

个人认为,next数组在求解的过程中,用到了KMP的思想,当前失配了,就回溯到上一个next,请见 j=next[j] ,先说个结论,如果到位置 i ,如果有 i%(i-next(i))==0 , 那说明字符串开始循环了,并且循环到 i-1 结束,为什么这样呢?

我们先假设到达位置 i-1 的时候,字符串循环了(到i-1完毕),那么如果到第i个字符的时候,失配了,根据next数组的求法,我们是不是得回溯?

然而回溯的话,由于字符串是循环的了(这个是假定的),next[i] 是不是指向上一个循环节的后面一个字符呢??

是的,上一个循环节的末尾是 next[i]-1 ,然后现在循环节的末尾是 i-1 ,然么循环节的长度是多少呢?

所以,我们有 (i - 1) - ( next[i] - 1 ) = i - next[i]  就是循环节的长度(假设循环成立的条件下),但是我们怎么知道这个循环到底成立吗?

现在我们已经假设了 0————i-1 循环了,那么我们就一共有i 个字符了,如果有 i % ( i - next[i] ) == 0,总的字符数刚好是循环节的倍数,那么说明这个循环是成立的。

注意还有一点,如果 next[i] == 0,即使符合上述等式,这也不是循环的,举个反例

0   1    2   3   4   5

a    b   c   a   b   d

-1   0   0   0   1   2

下标为1,2,3的next值均为0,那么 i%(i-next【i】)=i%i==0,但是这个并不是循环。

解释完毕,然后再来看下,为什么求出来的循环节长度是最小的呢?

因为next数组失配的时候,总是回溯到最近的循环节,所以i-next【i】就是最小的循环节长度

    为什么求出来的循环次数是最多的呢?

    循环节长度是最小的了,那么循环次数肯定是最多的了。

总结一下,如果对于next数组中的 i, 符合 i % ( i - next[i] ) == 0 && next[i] != 0 , 则说明字符串循环,而且

循环节长度为:   i - next[i]

循环次数为:       i / ( i - next[i] )

KMP 模板题 及next数组相关推荐

  1. Oulipo(欧力波)(经典kmp模板题) HDU-1686

    题目:Oulipo(欧力波) 中文大意 The French author Georges Perec (1936�C1982) once wrote a book, La disparition, ...

  2. POJ Oulipo(KMP模板题)

    题意:找出模板在文本串中出现的次数 思路:KMP模板题 #include<cstdio> #include<cstring> #include<cmath> #in ...

  3. POJ:3461-Oulipo(KMP模板题)

    原题传送:http://poj.org/problem?id=3461 Oulipo Time Limit: 1000MS Memory Limit: 65536K Description The F ...

  4. Codeforce-126B:Password(KMP模板题)

    题目链接:点击打开链接 题目大意: 给你一个串,让你求这个串的一个同时是前缀,后缀(这个说法好像不太对)且在串中出现过的最长子串. 举个例子: 对于串 fixprefixsdfix 就应该输出fix. ...

  5. hihoCoder 1015 (KMP模板题)

    题目链接:http://hihocoder.com/problemset/problem/1015 Time Limit:1000ms Case Time Limit:1000ms Memory Li ...

  6. Simpsons’ Hidden Talents【KMP模板题】

    Homer: Marge, I just figured out a way to discover some of the talents we weren't aware we had.  Mar ...

  7. poj-2406(kmp水题)

    题意:定义一个a*b=字符串a连接字符串b:给你一个字符串s,问你这个字符串最多能用多少个字符串t连接得到:例如:aaaa=4个a构成: 解题思路:kmp水题,next数组除了查找字串以外最广泛的一种 ...

  8. HDU1166 敌兵布阵(树状数组模板题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  9. hdu 1166 敌兵布阵 树状数组 模板题

    这题是树状数组入门的一模板题,非常基础,被小白成为"赤裸裸"的入门题,哈哈,一个plus,一个sum全部搞定 #include<stdio.h> #include< ...

最新文章

  1. 谷歌浏览器实现按下按键的脚本_chrome浏览器控制台创建js脚本并执行
  2. spark 资源参数调优
  3. php笔记之echo/print比较
  4. linux在主函数中调用进程,linux 调用进程
  5. byte数组存的是什么_结构体内存对齐是什么鬼?
  6. python正则匹配html标签_Python正则获取、过滤或者替换HTML标签的方法
  7. Phoenix 关联映射 Hbase表 获取不到数据,upsert hbase 列名为16进制字符
  8. c/c++排坑(4) -- c/c++中返回局部变量
  9. ubuntu使用python读串口_ubuntu16.04上Python串口编程学习1
  10. 计算机设计类自我诊断意见,汽车故障自我诊断.doc
  11. 华硕获奖方案-构建海量数据处理性能的医院集群系统
  12. 数据结构与算法必知基础知识
  13. arcgis中的图像裁剪
  14. 干货!详解服务器端和移动端性能测试指标
  15. NYOJ 366 STL 全排列
  16. maven创建eclipse wtp项目
  17. 借助大数据培育健康医疗产业群
  18. MOS管GS两端并联阻容的作用分析
  19. win7我的计算机无法搜索,解决Win7系统搜索功能不能用的问题
  20. java 系统工具类 查询内存 CPU 系统基本信息 SysInfoUtils

热门文章

  1. 计算机应用龙头300168,万达信息(300168)个股分析_牛叉诊股_同花顺财经
  2. MIT6828操作系统实践记录(一)
  3. springboot毕设项目海鲜配送管理系统q3m5u(java+VUE+Mybatis+Maven+Mysql)
  4. 家用汽车维修1:Android手机上的OBD II
  5. 群辉NAS开启和彩云WebDAV同步文件夹,如何优雅的薅移动羊毛
  6. STM32单片机汽车儿童安全系统高温一氧化碳报警WIFI-APP报警
  7. FFMPEG与RTMP
  8. 《仙剑奇侠传》观看日记(三)
  9. 【网络工程】广域网与接入网
  10. 工业表计图像读数解决方案流程