• Lyndon Word相关


    Lyndon Word

    定义

    对于字符串 (S),若 (S) 的最小后缀为其本身,那么称 (S)( ext{Lyndon}) 串(( ext{Lyndon Word})

    [S in L Rightarrow egin{cases} S是严格最小循环 \ minsuf(s)=s end{cases} ]

    性质

    (Border(S)=varnothing)

    推论

    如果 (u,v in L, u prec vRightarrow uv in L)

    (mathcal{Proof.})

    (1) s=u'v,u riangleleft u' Rightarrow uv < u'v)

    (2) ext{to prove uv<v})

    (2.1) u riangleleft v Rightarrow uv<v)

    (2.2) u sqsubseteq v Rightarrow v=uv',v<v' Leftrightarrow uv<uv' Leftrightarrow uv<v)

    (3) S=v',uv<v<v')

    (Q.E.D.)

    PS: ( riangleleft):严格小于,且不是前缀,必有一个字母不同,(sqsubseteq):前缀

    (ex.) 如果 (u,vin L,u<v Rightarrow u^av^bin L)

    显然。

    Lyndon 分解 (Lyndon Factorization)

    任意字符串 (s) 可以分解为 (s=s_1s_2s_3dots s_k),其中 (s_i)( ext{Lyndon}) 串,(s_i ge s_{i+1}),且这种分解方法是唯一的。

    (mathcal{Proof.})

    先证存在性

    初始时每段一个字符,然后不断地将相邻两段 (s_i<s_{i+1}) 合并。

    再证唯一性

    若有两种方案,取第一次不同的位置,设 (|s_i| > |s_i'|),令 (s_i=s_i's_{i+1}' dots s_k'pre(s_{k+1}',l)),则

    [s_i<pre(s_{k+1}',l)le s_{k+1}' le s_i' < s_i,矛盾 ]

    性质

    1. (s_k) 是最长的 ( ext{Lyndon suffix})
    2. (s_1) 是最长的 ( ext{Lyndon prefix})
    3. (s_k=minsuf(s))

    (mathcal{Proof.})

    画图比划一下,容易(是真的)证得。

    Duval 算法

    ( ext{Duval}) 算法可以 (O(n)) 时间 (O(1)) 额外空间内求出 (s[1dots n])( ext{Lyndon}) 分解。

    [CFL(s)=s_1 s_2 dots s_k, s.t. egin{cases} 1. s_i in L \ 2. s_1 ge s_2 ge dots ge s_kend{cases} ]

    (mathcal{Lemma.})

    若字符串 (v) 和字符 (c) 满足 (vc) 是某个 ( ext{Lyndon}) 串的前缀,则对于字符 (d>c)(vd)( ext{Lyndon}) 串。

    也就是说,如果 (uav in L),那么对于 ((uav)^kua')

    1. 如果 (a<a'),那么 ((uav)^kua' in L)

    2. 如果 (a>a'),那么 (forall w,(uav)^kua'w otin L)

      (Rightarrow CFL[(uav)^kua'w]=(uav)^kCFL(ua'w))

    因此,我们考虑下面这个算法过程:

    用三个循环变量 (i,j,k) 维持一个循环不变式:

    • (s[1 dots i-1] = s_1 s_2 cdots s_g) 是已经固定下来的分解,满足 (s_l)( ext{Lyndon}) 串,且 (s_l le s_{l+1})
    • (j-i) 是当前最长的 ( ext{Lyndon prefix}) 的长度,即 (s[j])(s[k])( ext{Lyndon Prefix}) 中对应位置的字符。
    • (k) 是当前读入的字符的位置。

    然后对于当前读入的字符 (a)

    • (a>s[j]),则令直接令 (s[idots k]) 成为新的 ( ext{Lyndon Prefix})
    • (a=s[j]),无法切割出新的划分,继续读入
    • (a<s[j]),则递归求解,先分解完 (s[idots t]) ,即 ((uav)^k),然后将指针指向 (t+1) 重新进行算法过程。

    Code

    int i, j, k;
    for (i = 1; i <= N; ) {
    	for (k = i, j = k + 1; j <= N && s[j] >= s[k]; ++j) {
    		if (s[j] > s[k]) k = i;
    		else ++k;
    	}
    	while (i <= k) { lyndon[++cnt] = i + j - k - 1; i += j - k; }
    }
    

    "Runs" Theorem

    先丢一个论文链接:The" Runs" Theorem

    Lyndon Array

    再说。

    [ZJOI2017] 字符串

    Description

    维护一个动态字符串 (s[1dots n]),字符串的字符集是所有 (|x|le 10^9) 的整数。要求支持两个操作:

    1. 输入 (l,r,d),对于所有 (lle i le r),将 (s[i]) 修改为 (s[i]+d)注意 (d) 可能是负数
    2. 输入 (l,r),输出子串 s([ldots r])字典序最小的后缀的起点位置。即,如果最小后缀是 (s[pdots r],(lle ple r)),请输出 (p)

    Solution

  • 相关阅读:
    C++位运算详解
    SQL语句获取时间的方法
    redis在windows下安装和ThinkPHP中使用
    数据同步存储过程代码
    C#重写OnKeyPress方法
    SQL Server 2008数据库生成数据库脚本(并带数据)
    C#中邮件的发送
    C#中DGV分页功能
    C#中保持文件夹A与B同步
    C# 获取文件大小,创建时间,文件信息,FileInfo类的属性表
  • 原文地址:https://www.cnblogs.com/newbielyx/p/12157972.html
Copyright © 2020-2023  润新知