KMP模板例题回文大师

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP模板例题回文大师相关的知识,希望对你有一定的参考价值。

1️⃣模板

⭐️s为长度更长的要进行匹配的字符串
⭐️p为长度小的模式串
ne[i]:表示模式串中以i下标为终点的最长公共前后缀的长度
j:始终是代表能够匹配公共前后缀的结尾位置

注意:ne[1]=0,所以i从2开始

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;

char s[N], p[N];
int ne[N];

int main()

	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int n, m;
	cin >> n >> m;
	
	cin >> s + 1 >> p + 1;
	for(int i = 2, j = 0; i <= m; i++)
	
		while(j && s[i] != s[j + 1]) j = ne[j];
		if(p[i] == p[j + 1]) j++;
		ne[i] = j;
	
	
	for(int i = 1, j = 0; i <= n; i++)
	
		while(j && s[i] != p[j + 1]) j = ne[j];
		if(s[i] == p[j + 1]) j++;
		if(j == m) j = ne[j]; //匹配成功 
	
	return 0;



2️⃣例题:回文大师

链接:
https://ac.nowcoder.com/acm/contest/23481/A

其实就是求对于每个i, [ 1 , i ] [1,i] [1,i] [ j , j + i − 1 ] [j,j+i-1] [j,j+i1]区间的数构成回文的j的个数


KMP:
求出数组anext数组,转化为用数组a对数组从后向前匹配。
也就是对于a数组进行翻转,反转后的的数组记作b
a数组取匹配b数组,对于每次匹配产生一个j,表明在j位置匹配成功一次,所以用f数组记录结果。

最后因为长度长的片段匹配成功,那么在这个长片段中的短片段也一定会匹配成功 。

n e x j nex_j nexj看作 j j j的父亲,则 n e x nex nex数组构成了一颗以 0 0 0为根节点的树(因为 0 ≤ n e x j < j 0\\le nex_j<j 0nexj<j),跑完 a a a b b b的匹配后再在树上进行子树求和即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;

int ne[N];
int a[N]; 
int f[N];

int main()

	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];
	
	for(int i = 2, j = 0; i <= n; i++) 
	
		while(j && a[j + 1] != a[i]) j = ne[j];
		if(a[j + 1] == a[i]) j++;
		ne[i] = j;
	
	
	for(int i = n, j = 0; i >= 0; i--)
	
		while(j && a[j + 1] != a[i]) j = ne[j];
		if(a[j + 1] == a[i]) j++;
		f[j] ++;
	
	
	for(int i = n; i; i--)
		f[ne[i]] += f[i];

	for(int i = 1; i <= n; i++)
		cout << f[i] << " \\n"[i == n];
	return 0;


以上是关于KMP模板例题回文大师的主要内容,如果未能解决你的问题,请参考以下文章

算法进阶面试题01——KMP算法详解输出含两次原子串的最短串判断T1是否包含T2子树Manacher算法详解使字符串成为最短回文串

字符串小结

kmp模板

扩展KMP,附上例题(HDU - 4333 Revolving Digits)

2022牛客寒假算法基础集训营6 全部题解

2022牛客寒假算法基础集训营6 全部题解