KMP算法题集
模板
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 1e6 + 10;
const int MAXM = 1e3 + 10;
char a[MAXN], b[MAXM];
int next[MAXM], lena, lenb;
void get_next()
{
next[1] = 0; int j = 0;
_for(i, 2, lenb)
{
while(j > 0 && b[j + 1] != b[i]) j = next[j];
if(b[j + 1] == b[i]) j++;
next[i] = j;
}
}
void kmp()
{
int j = 0;
_for(i, 1, lena)
{
while(j > 0 && (j == lenb || b[j + 1] != a[i])) j = next[j];
if(b[j + 1] == a[i]) j++;
if(j == lenb) { printf("%d %d\n", i - lenb + 1, i); return; }
}
puts("NO");
}
int main()
{
scanf("%s%s", a + 1, b + 1);
lena = strlen(a + 1); lenb = strlen(b + 1);
get_next();
kmp();
return 0;
}
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 1e6 + 10;
char a[MAXN], b[MAXN];
int next[MAXN], lena, lenb;
void get_next()
{
next[1] = 0; int j = 0;
_for(i, 2, lena)
{
while(j > 0 && a[j + 1] != a[i]) j = next[j];
if(a[j + 1] == a[i]) j++;
next[i] = j;
}
}
int kmp()
{
int res = 0, j = 0;
_for(i, 1, lenb)
{
while(j > 0 && a[j + 1] != b[i]) j = next[j];
if(a[j + 1] == b[i]) j++;
if(j == lena) { res++; j = next[j]; }
}
return res;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s%s", a + 1, b + 1);
lena = strlen(a + 1); lenb = strlen(b + 1);
get_next();
printf("%d\n", kmp());
}
return 0;
}
重复子串结论
有一个结论。
对于字符串S[1~i],如果i % (i - next[i]) == 0,那么这个字符串就由很多个重复的子串构成(形如abababab)
每个循环节等于S[1~i-next[i]],循环节的个数为i / (i - next[i])
这个结论很好证明,用笔画一下就可以发现这个性质
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 1e6 + 10;
char a[MAXN];
int next[MAXN], lena;
void get_next()
{
next[1] = 0; int j = 0;
_for(i, 2, lena)
{
while(j > 0 && a[j + 1] != a[i]) j = next[j];
if(a[j + 1] == a[i]) j++;
next[i] = j;
}
}
int main()
{
while(scanf("%s", a + 1))
{
if(a[1] == '.') break;
lena = strlen(a + 1);
get_next();
if(lena % (lena - next[lena]) == 0)
printf("%d\n", lena / (lena - next[lena]));
else puts("1");
}
return 0;
}
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 1e6 + 10;
char a[MAXN];
int next[MAXN], lena;
void get_next()
{
next[1] = 0; int j = 0;
_for(i, 2, lena)
{
while(j > 0 && a[j + 1] != a[i]) j = next[j];
if(a[j + 1] == a[i]) j++;
next[i] = j;
}
}
int main()
{
scanf("%s", a + 1);
lena = strlen(a + 1);
get_next();
_for(i, 2, lena)
if(i % (i - next[i]) == 0 && i / (i - next[i]) > 1)
printf("%d %d\n", i, i / (i - next[i]));
return 0;
}
next数组应用
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 1e6 + 10;
char a[MAXN];
int next[MAXN], lena;
void get_next()
{
next[1] = 0; int j = 0;
_for(i, 2, lena)
{
while(j > 0 && a[j + 1] != a[i]) j = next[j];
if(a[j + 1] == a[i]) j++;
next[i] = j;
}
}
int main()
{
while(~scanf("%s", a + 1))
{
lena = strlen(a + 1);
get_next();
int j = lena;
stack<int> s;
while(j) s.push(j), j = next[j];
while(!s.empty()) printf("%d ", s.top()), s.pop();
puts("");
}
return 0;
}
综合题
这道题不知道为什么一直A不了。先放着
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 1e4 + 10;
const int MAXM = 75 + 10;
char s[MAXN][MAXM], t[MAXN];
int next[MAXN], f[MAXN];
int n, m, r, c, j;
int get_r() //一行看作一个字符,很牛逼。
{
next[1] = 0;
for(int i = 2, j = 0; i <= n; i++)
{
if(j > 0 && strcmp(s[j + 1], s[i])) j = next[j];
if(!strcmp(s[j + 1], s[i])) j++;
next[i] = j;
}
return n - next[n];
}
int get_c()
{
memset(f, 0, sizeof(f));
_for(i, 1, n)
_for(len, 1, m)
REP(j, 0, m)
{
if(s[i][j] != s[i][j % len]) break; //这个操作要学学
if(j == m - 1) f[len]++;
}
_for(i, 1, m) //用桶这个思路很妙
if(f[i] == n)
return i;
}
int main()
{
scanf("%d%d", &n, &m);
_for(i, 1, n) scanf("%s", s[i]);
printf("%d\n", get_r() * get_c());
return 0;
}
KMP算法题集的更多相关文章
- 51nod 贪心算法题集
2070 最小罚款: 题意:初始有n元,每个任务有2个参数:t和w,<=t时刻前完成任务才可避免造成损失w.问:如何安排才能尽可能避免损失?一个任务执行时间是一个单位时间. 分析:任务按时间排个 ...
- 经典算法题每日演练——第七题 KMP算法
原文:经典算法题每日演练--第七题 KMP算法 在大学的时候,应该在数据结构里面都看过kmp算法吧,不知道有多少老师对该算法是一笔带过的,至少我们以前是的, 确实kmp算法还是有点饶人的,如果说红黑树 ...
- hihoCoder #1015 : KMP算法【KMP裸题,板子】
#1015 : KMP算法 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在 ...
- 串的模式之kmp算法实践题
给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出.如果找不到,则输出“Not ...
- hdu 1711 KMP算法模板题
题意:给你两个串,问你第二个串是从第一个串的什么位置開始全然匹配的? kmp裸题,复杂度O(n+m). 当一个字符串以0为起始下标时.next[i]能够描写叙述为"不为自身的最大首尾反复子串 ...
- 51NOD欧姆诺姆和项链——KMP算法(非水题)
>>点击进入原题测试<< 思路:好久不见,今天要开始真正写题了.这个题之前我的理解有点问题,导致写了很久最终都是一直都只能过样例.需要注意的是输出中每一个“1”都是和别的输出相 ...
- 面试必备:高频算法题终章「图文解析 + 范例代码」之 矩阵 二进制 + 位运算 + LRU 合集
Attention 秋招接近尾声,我总结了 牛客.WanAndroid 上,有关笔试面经的帖子中出现的算法题,结合往年考题写了这一系列文章,所有文章均与 LeetCode 进行核对.测试.欢迎食用 本 ...
- 笔试算法题(52):简介 - KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm)
议题:KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm) 分析: KMP算法用于在一个主串中找出特定的字符或者模式串.现在假设主串为长度n的数组T ...
- LeetCode刷题--基础知识篇--KMP算法
KMP算法 关于字符串匹配的算法,最知名的莫过于KMP算法了,尽管我们日常搬砖几乎不可能去亲手实现一个KMP算法,但作为一种算法学习的锻炼也是很好的,所以记录一下. KMP算法是根据三位作者(D.E. ...
随机推荐
- SpringBoot-CommandLineRunner实现预操作
前提:在使用SpringBoot构建项目时,我们通常需要做一些预先操作(类似开机自启动).而SpringBoot正好提供了一个简单的方式来实现–CommandLineRunner. CommandLi ...
- Java基础学习总结(61)——Java项目开发要注意的60个问题
1. 首先写代码的时候最好不要有缺陷.最好的修复方法就是让 bug 胎死腹中. 良好的单元测试 强制数据库约束 使用输入验证框架 避免未实现的"else"条件 在应用到主程序之前知 ...
- LoadRunner结果分析 – TPS
针对吞吐率和 TPS 的关系,这个在结果分析中如何使用,就个人经验和朋友讨论后,提出如下建议指导,欢迎同僚指正. 相关定义 响应时间 = 网络响应时间 + 应用程序响应时间 响应时间 =(N1+N2+ ...
- BZOJ 3674 可持久化并查集加强版(路径压缩版本)
/* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...
- mengento 数据库模型
- java多线程具体总结
一.Thread.start()与Thread.run()的差别 通过调用Thread类的start()方法来启动一个线程.这时此线程是处于就绪状态,并没有运行.然后通过此Thread类调用方法run ...
- JavaScript 获取小数任一小数点后的位数的小数
用Javascript取float型小数点后两位,例22.127456取成22.13,怎样做? 1.这样的方法最不推荐: function get(){ var s = 22.127456 + &qu ...
- WebGL 权威资源站小聚
WebGL 权威资源站小聚 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句 ...
- UVALive 6663 Count the Regions 离散+bfs染色_(:зゝ∠)_
题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=4675">点击打开链接 gg.. ...
- Linux以下基于TCP多线程聊天室(client)
不怎么会弄这个博客的排版,就直接将代码附上: 主要是使用多线程去等待接受数据和发送数据.以下是client的代码: tcpsed.h文件 1 2 3 4 5 6 7 8 9 10 11 12 13 1 ...