zoukankan      html  css  js  c++  java
  • Lyndon 分解

    Lyndon 分解学习笔记

    定义

    如果串 (s) 的所有后缀 (t) 均大于 (s),那么称 (s) 为 Lyndon 串(Lyndon Word)。显然,这等价于 (s) 为其最小循环表示。

    一个串 (s) 的 Lyndon 分解为将 (s) 拆分为若干部分 (s_1s_2...s_k),满足 (s_i) 为 Lyndon 串,且 (s_1 ge s_2 ge s_3 ge ... ge s_k)

    性质

    • (u,v) 为 Lyndon 串,且 (u<v),则 (uv) 为 Lyndon 串。

    • 一个串的 Lyndon 分解有且仅有一种方案。(当 (s_i < s_{i+1}) 时合并两串得到新 Lyndon 串,一直这么做可得到一种方案)(如果存在多种方案,不妨设 (s_i' = s_i + t),其中 (s_i) 之前部分两种方案一致。那么 (t > s_i'),那么 (s_{i+1} > s_i)

    • 如果 (sc) 可以作为 Lyndon 串的前缀,其中 (|c| = 1),那么对于一个比 (c) 大的字符 (d),有 (sd) 一定是 Lyndon 串。

    • 如果 (s_1) 为 Lyndon 串且 (s_1 > s_2),那么 (s_1 > s_2 + s_2)

    • Lyndon 串不含 border

    构造方法

    因为 Lyndon 分解的限制只在相邻两个 Lyndon 串上,我们只用管最近的 Lyndon 串即可。

    将串 (s) 分为 已经确定好的 Lyndon 串 (A),未确定的(可能出现循环的)串 (B),以及尚未考虑的串 (C)

    假设 (B) 的周期为 (l),每个循环节均为一个 Lyndon 串。如果 (C) 的第一个字符 (s_k)(s_{k-l}) 大,那么可以将 (B)(s_k) 合并成一个 Lyndon 串,周期为 (|B|+ 1)。如果 (C) 的第一个字符 (s_k < s_{k-l}),那么 (B) 中前面所有满的循环节都可以拆出来成为 Lyndon 串了,因为它们不可能继续和 (s_k) 拼一块。如果 (s_k = s_{k-l}),那么我们只好将 (s_k) 加入 (B) 继续观察。

    均摊复杂度为 (O(n))

    for (int i = 1; i <= n; ) {//i:A后面那个位置
    	int j = i, k = j + 1;//j:k-l
    	while (k <= n && s[k] >= s[j]) {
    		if (s[k] == s[j])	++j;
    		else	j = i;
    		++k;
    	}
    	while (i <= j) {
    		Push(i, i + (k-j) - 1);//i...i+k-j-1 为一个 Lyndon 串
    		i += (k - j);
    	}
    }
    

    最小表示

    如何利用 Lyndon 分解求一个串 (s) 的最小表示?

    (ss) 进行 Lyndon 分解,其中开头在 (1...n) 的 Lyndon Word 的开头 (i) 记为最小表示的开头

    因为后面的肯定不行(其实会发现后面好像都成了一大块 Lyndon Word,除了循环串),前面的 Lyndon 串比这个串大的也肯定不行,前面的和它相等的也都可以。

    不过如果前面出现和它相等的 Lyndon Word 的话一定是出现了循环串(如 abab -> abababab)否则后面不可能再分解出 Lyndon 串了,因为分解出的 Lyndon 串必须小于等于前面和它相同的部分的 Lyndon Word,这只有循环串才能实现。

    for (int i= 1; i <= n; ++i)	s[i + n] = s[i];
    int ans = 0;
    for (int i = 1; i <= n; ) {
    	int j = i, k = i + 1; ans = i;
    	while (k <= n + n && s[k] >= s[j]) {
    		if (s[k] == s[j])	++j;
    		else	j = i;
    		++k;
    	}
    	while (i <= j) i += (k - j);
    }
    
  • 相关阅读:
    python常见异常
    python+selenium动态抓取网页数据
    python基于scrapy配置日志
    Python依赖
    nginx配置详解
    Centos 用户登录失败N次后锁定用户禁止登陆
    CENTOS 7 firewalld详解,添加删除策略
    Centos7搭建Zookeeper 3.4.14集群
    Centos7安装FastDFS整合nginx
    VMware VCSA 6.7配置vSAN存储
  • 原文地址:https://www.cnblogs.com/JiaZP/p/14296459.html
Copyright © 2011-2022 走看看