1 条题解

  • 0
    @ 2025-8-24 22:17:33

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar wucstdio
    这个家伙不懒,但还是什么都没留下

    搬运于2025-08-24 22:17:33,当前版本为作者最后更新于2020-02-18 16:33:06,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    大概是我贡献的第二道模板?

    Lyndon\text{Lyndon} 分解详解

    我们定义一个串是 Lyndon\text{Lyndon} 串,当且仅当这个串的最小后缀就是这个串本身。

    该命题等价于这个串是它的所有循环表示中字典序最小的。


    引理 1:如果 uuvv 都是 Lyndon\text{Lyndon} 串并且 u<vu<v,则 uvuv 也是 Lyndon\text{Lyndon} 串。

    证明:

    1、若 len(u)len(v)\operatorname{len}(u)\ge\operatorname{len}(v)

    这时,uuvv 这两个串在 len(v)\operatorname{len}(v) 之前就出现了不同的字符,所以有 v>uvv>uv,又因为 vvLyndon\text{Lyndon} 串,所以 vv 的所有后缀都大于 vv,所以 uvuv 的所有后缀都大于 uvuv,故 uvuvLyndon\text{Lyndon} 串。

    2、若 len(u)<len(v)\operatorname{len}(u)<\operatorname{len}(v)

    uu 不是 vv 的前缀,那么有 v>uvv>uv,得证。

    uuvv 的前缀,那么如果 v<uvv<uv,则必有 v[len(u)+1:]<vv[\operatorname{len}(u)+1:]<v(也就是各自去掉了前 u|u| 个字符),矛盾。


    我们定义一个串 SSLyndon\text{Lyndon} 分解为一个字符串序列 A1,A2,,AmA_1,A_2,\dots,A_m,满足:

    • i[1,m]\forall i \in [1,m],满足 AiA_iLyndon\text{Lyndon} 串。
    • i[1,m1]\forall i \in [1,m-1],满足 AiAi+1A_i\ge A_{i+1}

    可以证明这种划分存在且唯一。

    存在性证明

    初始令 m=Sm=|S| 并且 Ai=S[i]A_i=S[i],然后每次不断找到 Ai<Ai+1A_i<A_{i+1} 并且合并为一个串。最后一定能使得所有的 AiAi+1A_i\ge A_{i+1}

    唯一性证明

    假设对于字符串 SS 存在两个 Lyndon\text{Lyndon} 分解:

    S=A1A2AiAi+1Ai+2Am1S=A_1A_2\cdots A_iA_{i+1}A_{i+2}\cdots A_{m_1} $$S=A_1A_2\cdots A_iA^\prime_{i+1}A^\prime_{i+2}\cdots A^\prime_{m_1} $$

    不妨设 $\operatorname{len}(A_{i+1})>\operatorname{len}(A^\prime_{i+1})$。

    观察 Ai+1A_{i+1} 在第二种分解中的对应情况。假设 $A_{i+1}=A^\prime_{i+1}A^\prime_{i+2}\cdots A^\prime_{k}A^\prime_{k+1}[:l]$。

    那么由 Lyndon\text{Lyndon} 串的性质可知:

    $$A_{i+1}<A^\prime_{k+1}[:l]\le A^\prime_{k+1}\le A^\prime_{i+1}<A_{i+1} $$

    矛盾。


    引理2:若字符串 vv 和字符 cc 满足 vcvc 是某个 Lyndon\text{Lyndon} 串的前缀,则对于字符 d>cd>cvdvdLyndon\text{Lyndon} 串。

    证明:

    设该 Lyndon\text{Lyndon} 串为 v+c+tv+c+t

    i[2,v],v[i:]+c+t>v+c+t\forall i \in [2,|v|],v[i:]+c+t>v+c+t,也就是说 v[i:]+cvv[i:]+c\ge v

    所以 v[i:]+d>v[i:]+cvv[i:]+d>v[i:]+c\ge v

    同时因为 c>v[1]c>v[1],我们有 d>c>v[1]d>c>v[1]

    v+dv+d 是一个 Lyndon\text{Lyndon} 串。


    Duval\text{Duval} 算法

    这个算法可以在 O(n)O(n) 时间复杂度,O(1)O(1) 空间复杂度内求出一个串的 Lyndon\text{Lyndon} 分解。

    该算法中我们仅需维护三个变量 i,j,ki,j,k

    维持一个循环不变式:

    • s[:i1]=s1s2sgs[:i-1]=s_1s_2\cdots s_g 是固定下来的分解,也就是 l[1,g],sl\forall l\in[1,g],s_lLyndon\text{Lyndon} 串且 sl>sl+1s_l>s_{l+1}
    • s[i,k1]=th+v(h>1)s[i,k-1]=t^h+v(h>1) 是没有固定的分解,满足 ttLyndon\text{Lyndon} 串,且 vvtt 的可为空的不等于 tt 的前缀,且有 sg>s[i,k1]s_g>s[i,k-1]

    如下图:

    当前读入的字符是 s[k]s[k],令 j=ktj=k-|t|

    分三种情况讨论:

    • s[k]=s[j]s[k]=s[j] 时,直接 kk+1,jj+1k\leftarrow k+1,j\leftarrow j+1,周期 kjk-j 继续保持
    • s[k]>s[j]s[k]>s[j] 时,由引理 2 可知 v+s[k]v+s[k]Lyndon\text{Lyndon} 串,由于 Lyndon\text{Lyndon} 分解需要满足 sisi+1s_i\ge s_{i+1},所以不断向前合并,最终整个 th+v+s[k]t^h+v+s[k] 形成了一个新的 Lyndon\text{Lyndon} 串。
    • s[k]<s[j]s[k]<s[j] 时,tht^h 的分解被固定下来,算法从 vv 的开头处重新开始。

    复杂度分析:ii 只会单调往右移动,同时 kk 每次移动的距离不会超过 ii 移动的距离,所以时间复杂度是 O(n)O(n) 的。

    代码如下:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    char s[5000005];
    int n,ans;
    int main()
    {
    	scanf("%s",s+1);
    	n=(int)strlen(s+1);
    	for(int i=1;i<=n;)
    	{
    		int j=i,k=i+1;//初始化
    		while(k<=n&&s[j]<=s[k])
    		{
    			if(s[j]<s[k])j=i;//合并为一整个
    			else j++;//保持循环不变式
    			k++;
    		}
    		while(i<=j)//从v的开头重新开始
    		{
    			ans^=i+k-j-1;
    			i+=k-j;
    		}
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    5139
    时间
    300ms
    内存
    500MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者