前缀函数

字符串的前缀函数

概念
令字符串为s
令π[i]表示s的[0,i]区间内 真前缀s[0...k-1]和真后缀s[i-k+1...i]相等(不能重合!!!)
长度为k,若有多组,k取最大值,没有,k取0,k即为前缀函数π[i]的值
特别规定π[0]=0

例子 来源oi-wiki
举例来说,字符串 abcabcd,
π[0]=0,因为 a 没有真前缀和真后缀,根据规定为 0
π[1]=0,因为 ab 无相等的真前缀和真后缀
π[2]=0,因为 abc 无相等的真前缀和真后缀
π[3]=1,因为 abca 只有一对相等的真前缀和真后缀:a,长度为 1
π[4]=2,因为 abcab 相等的真前缀和真后缀只有 ab,长度为 2
π[5]=3,因为 abcabc 相等的真前缀和真后缀只有 abc,长度为 3
π[6]=0,因为 abcabcd 无相等的真前缀和真后缀

算法
1.朴素前缀数组计算O(n^3)
2.优化1
考虑相邻的前缀数组值最多增加1
当移动到下一个位置时,前缀函数的值要么增加一,要么维持不变,要么减少
复杂度降为O(n^2)
3.优化2
考虑如果π[i+1]可以等于π[i]+1,即s[i+1]==s[π[i]],直接转移--------------1
但是不能的话,即s[i+1]!=s[π[i]],我们就要找到仅次于π[i]的第二长度j------2
第二长度等价于s[j-1]的前缀函数值
再次比较s[i+1]和s[j],不能的话重复2

++优化的代码

vector<int> prefix_func(string s) {
	
	int n=s.length();
	vector<int> pi(n);
	for(int i=1;i<n;i++) {
		
		int j=pi[i-1];
		while(j>0&&s[i]!=s[j]) j=pi[j-1];
		if(s[i]==s[j]) j++;
		pi[i]=j;
		
	}
	return pi;
	
}

posted @   Diamondan  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示