版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ike940067893/article/details/86550793
KMP
- 重点:失配
数组
- 意义: 表示在 内最长相同前后缀的长度
- 图示:
- 此时 ,即指向最长相同前后缀的后一位置,数值上是最长相同钱后缀的长度
- 求法:假设我们已知
,想要求
- 当 ,显然有
- 当 ,那么就要往更前面找。因为已知 ,所以必定出现如下①、②的两段是 的最长相同前后缀。 是 ,所以只要 与 配对即可。如果不行,那就如此反复下去,一直到头。其实也可以把这个过程看作自己和自己匹配
一道题目:BZOJ 4974[Lydsy1708月赛]字符串大师
题目链接:BZOJ 4974[Lydsy1708月赛]字符串大师
- 稍微做判断可得到,给出的 数组满足性质:
- 于是求出 数组后考虑怎么构造,只要满足位置 的值等于 的值就行了。如果 等于0,就在沿nxt移动过程中,打一下标记,最后取最小字典序就行了
AC code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int n, nxt[MAXN], str[MAXN];
bool vis[MAXN][26];
int main()
{
scanf("%d", &n);
for(int i = 1, x; i <= n; ++i)
scanf("%d", &x), nxt[i] = i-x;
nxt[0] = -1;
for(int i = 0; i < n; ++i)
{
int j = nxt[i], k;
while(nxt[i+1] != j+1)
vis[i][str[j]] = 1, j = nxt[j];
if(~j) str[i] = str[j];
else
{
for(k = 0; k < 26; ++k)
if(!vis[i][k]) break;
str[i] = k;
}
}
for(int i = 0; i < n; ++i) putchar('a'+str[i]);
}