前缀函数学习

前缀函数

在oi-wiki上学习了前缀函数,自己也总结一下。
定义: p i [ i ] = m a x ( j ) , s [ 0.. j ] = s [ i − j + 1 , i ] pi[i]=max(j),s[0..j]=s[i-j+1,i] pi[i]=max(j),s[0..j]=s[ij+1,i]
O(n)计算方法:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
int p[maxn];
char s[maxn];
void getpi(int n)
{
    p[0]=0;
    for(int i=1;i<n;i++)
    {
        int j=p[i-1];
        while(j&&s[j]!=s[i]) j=p[j-1];
        if(s[i]==s[j]) j++;
        p[i]=j;
    }
}

应用:

  1. 在字符串中查找:在文本t中查找s,构造字符串s+#+t,求前缀函数,统计t中p[i]=|s|的数目。
  2. 字符串的周期:字符串长度一定要是整数周期倍,n-p[n-1]为最小周期。
  3. 统计前缀出现次数,若相同字符串,对于每个i,长度为p[i],p[p[i]-1]…的前缀都出现了,且后端点为i,统计即可。若要统计s的前缀在t中出现次数,则需构造s+#+t来做。
  4. 一个字符串中本质不同的串:一个字符一个字符处理,当前已处理字符串为s,新增字符c,构造t=~(s+c)(翻转),计算前缀函数,新增子串数量|s|+1-max(p[i]).
    利用前缀函数构造自动机:待补

z函数

定义:z函数为n个数,z[i]代表以s[i]开头且是s的一个前缀的最长字符串长度。
最优求解算法和马拉车的求解有点像:

void getz(int n)
{
    int l=0,r=0;
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=z[i-l];
        while(i+z[i]<n&&s[i+z[i]]==s[z[i]]) z[i]++;
        if(i+z[i]-1>r) 
        {
            l=i,r=i+z[i]-1;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值