KMP中next数组的理解与应用
理解
1、next数组一直往前走
next数组一直往前走,得到的所有前缀也是当前主串的后缀,当然了,也是当前主串的前缀。
2、周期性字符串
1、周期性字符串$\Leftrightarrow n \,\% \, (n-next[n]) == 0 \ \&\& \ next[n] {\ } {\!}!{=} \ 0 $,循环节长度是$n-next[n]$。
2、next数组往前跳的步长是一样的,除了最后一次。即$i-next[i]$保持恒定。
应用
- 题目一:Period
思路:先求出next数组,然后遍历一遍next数组得到所有字符结尾的字符串循环节的长度及个数
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int maxn = + ;
int nexts[maxn],n;
char s[maxn]; void pre_kmp()
{
int i = , j = nexts[] = -;
while (i < n)
{
while (j != - && s[i] != s[j]) j = nexts[j]; //当前不匹配,j回退,寻找是否存在一个长度较小的字串和开头的字串相等
nexts[++i] = ++j; //j等于已匹配的长度,如果当前位置也匹配,则nexts直接为j+1
}
} void slove()
{
pre_kmp();
for(int i = ; i <= n; i++)
if (i % (i - nexts[i]) == && nexts[i] != ) printf("%d %d\n", i, i / (i - nexts[i]));
} int main()
{
int T = ;
while (scanf("%d",&n) == && n)
{
scanf("%s", s);
s[n] = '#';
if (T) printf("\n");
printf("Test case #%d\n", ++T);
slove();
}
return ;
}
- 题目二:Power Strings
思路:先求next数组,再直接求循环节
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int maxn = + ;
int nexts[maxn],n;
char s[maxn]; void pre_kmp()
{
int i = , j = nexts[] = -;
//int n = strlen(s);
while (i < n)
{
while (j != - && s[i] != s[j]) j = nexts[j]; //当前不匹配,j回退,寻找是否存在一个长度较小的字串和开头的字串相等
nexts[++i] = ++j; //j等于已匹配的长度,如果当前位置也匹配,则nexts直接为j+1
}
} void slove()
{
pre_kmp();
if (n % (n - nexts[n]) != ) printf("1\n");
else printf("%d\n", n / (n - nexts[n]));
} int main()
{
int T = ;
while (scanf("%s", s) == && s[] != '.')
{
n = strlen(s);
s[n] = '#';
slove();
}
return ;
}
- 题目三:Count The String
思路:求所有前缀出现的次数和,由于next数组回退得到的前缀也是主串的后缀,所以所有next回退的次数加上本身的一次取模就是答案。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int mod = ;
const int maxn = + ;
int nexts[maxn], n;
char s[maxn]; void pre_kmp()
{
int i = , j = nexts[] = -;
//int n = strlen(s);
while (i < n)
{
while (j != - && s[i] != s[j]) j = nexts[j]; //当前不匹配,j回退,寻找是否存在一个长度较小的字串和开头的字串相等
nexts[++i] = ++j; //j等于已匹配的长度,如果当前位置也匹配,则nexts直接为j+1
}
} void slove()
{
int ans = n;
pre_kmp();
for (int i = n; i > ; i--)
{
int k = nexts[i];
while (k > )
{
ans = (ans + ) % mod;
k = nexts[k];
}
}
printf("%d\n", ans);
} int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
scanf("%s", s);
slove();
}
return ;
}
- 题目四:Cyclic Nacklace
思路:题目大意:问至少添加多少个字符,使得这个字符串有至少两个循环节。若本身有两个循环节返回0,否则补充至两个循环节。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int mod = ;
const int maxn = + ;
int nexts[maxn], n;
char s[maxn]; void pre_kmp()
{
int i = , j = nexts[] = -;
n = strlen(s);
while (i < n)
{
while (j != - && s[i] != s[j]) j = nexts[j]; //当前不匹配,j回退,寻找是否存在一个长度较小的字串和开头的字串相等
nexts[++i] = ++j; //j等于已匹配的长度,如果当前位置也匹配,则nexts直接为j+1
}
} void slove()
{
pre_kmp();
int len = n - nexts[n];
if (n % len == && nexts[n] != ) printf("0\n");
else printf("%d\n", len - nexts[n] % len);
} int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%s", s);
slove();
}
return ;
}
参考链接:
1、https://vjudge.net/contest/278481#overview
2、https://blog.csdn.net/hkh746392783/article/details/52015293
KMP中next数组的理解与应用的更多相关文章
- KMP中next数组的理解
next数组是KMP的核心,但对于next数组我们总是有时候感觉明白了,但有时候又感觉没明白,现在我就说下我自己对KMP中next数组的理解,首先next[i]上的数字的意义,next[i]表示的是当 ...
- POJ 2752 KMP中next数组的理解
感觉这里讲的挺好的.http://cavenkaka.iteye.com/blog/1569062 就是不断递归next数组.长度不断减小. 题意:给你一个串,如果这个串存在一个长度为n的前缀串,和长 ...
- POJ 2752 KMP中next数组的应用
题意: 让你从小到大输出给的字符串中既是前缀又是后缀的子串的长度. 思路: 先要了解这个东西: KMP中next数组表示的含义:记录着字符串匹配过程中失配情况下可以向前多跳几个字符,它描述的也是子串的 ...
- KMP算法中next数组的理解与算法的实现(java语言)
KMP 算法我们有写好的函数帮我们计算 Next 数组的值和 Nextval 数组的值,但是如果是考试,那就只能自己来手算这两个数组了,这里分享一下我的计算方法吧. 计算前缀 Next[i] 的值: ...
- poj 2406 Power Strings (kmp 中 next 数组的应用||后缀数组)
http://poj.org/problem?id=2406 Power Strings Time Limit: 3000MS Memory Limit: 65536K Total Submiss ...
- E - Period(KMP中next数组的运用)
一个带有 n 个字符的字符串 s ,要求找出 s 的前缀中具有循环结构的字符子串,也就是要输出具有循环结构的前缀的最后一个数下标与其对应最大循环次数.(次数要求至少为2) For each prefi ...
- 对于kmp求next数组的理解
首先附上代码 1 void GetNext(char* p,int next[]) 2 { 3 int pLen = strlen(p); 4 next[0] = -1; 5 int k = -1; ...
- HDU 3746 Cyclic Nacklace(求补齐循环节最小长度 KMP中next数组的使用 好题!!!)
Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- POJ1961(kmp中Next数组的性质)
对于某个位置i,i - Next[i]是循环节长度,i整除(i - Next[i])时是完整的几个循环元. ; int n, kase, Next[maxn]; char ch[maxn]; inli ...
随机推荐
- beego5---gosqlite安装
WindowsWindows下的安装也非常简单,只要到 SQLite3 的下载页面,下载 Windows 下的预编译包 DLL 的压缩包(sqlite-dll-win32-x86-XXX.zip),然 ...
- POJ3264 Balanced Lineup —— 线段树单点更新 区间最大最小值
题目链接:https://vjudge.net/problem/POJ-3264 For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000 ...
- winform 无法修改控件的location
dock and location 是因为设置了控件的Dock,导致无法修改
- 深入了解以太坊虚拟机第4部分——ABI编码外部方法调用的方式
在本系列的上一篇文章中我们看到了Solidity是如何在EVM存储器中表示复杂数据结构的.但是如果无法交互,数据就是没有意义的.智能合约就是数据和外界的中间体. 在这篇文章中我们将会看到Solidit ...
- CF 949 D Curfew —— 二分答案
题目:http://codeforces.com/contest/949/problem/D 先二分一个答案,让两边都至少满足这个答案: 由于越靠中间的房间越容易满足(被检查的时间靠后),所以策略就是 ...
- 【转载】Nginx 的工作原理 和优化
1. Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(locati ...
- Linux 常用命令一 ls
一.ls命令 用于查看目录下的文件信息. ls 当前目录下都有哪些文件: wang@wang:~$ ls examples.desktop workpalce 模板 图片 下载 桌面 tools 公共 ...
- bzoj 4080: [Wf2014]Sensor Network【瞎搞+随机化】
参考:https://blog.csdn.net/YihAN_Z/article/details/73380387 一点都不想写正解.jpg random_shuffle一下然后贪心的加点,和ans取 ...
- bzoj 4916: 神犇和蒟蒻【欧拉函数+莫比乌斯函数+杜教筛】
居然扒到了学长出的题 和3944差不多(?),虽然一眼看上去很可怕但是仔细观察发现,对于mu来讲,答案永远是1(对于带平方的,mu值为0,1除外),然后根据欧拉筛的原理,\( \sum_{i=1}^{ ...
- 通过爬虫爬取四川省公共资源交易平台上最近的招标信息 --- URLConnection
通过爬虫爬取公共资源交易平台(四川省)最近的招标信息 一:引入JSON的相关的依赖 <dependency> <groupId>net.sf.json-lib< ...