zoukankan      html  css  js  c++  java
  • [LOJ129] Lyndon 分解

    Lyndon 串:(s) 的字典序严格小于 (s) 的所有后缀的字典序。

    性质:Lyndon 串是它的所有循环同构中最小的一个。

    近似 Lyndon 串:若 (s) 为 Lyndon 串,则 (xx....xx') 是近似 Lyndon 串,其中 (x')(x) 的前缀。

    Lyndon 分解:将一个串 (S) 分解为 (s_1s_2...s_k),每一个串都是 Lyndon 串,且 (s_i ge s_{i+1})

    性质:Lyndon 分解是唯一的。对于两个 Lyndon 串 (s,t),如果 (s<t),则 (st) 是 Lyndon 串。


    用后缀数组求解 Lyndon 分解

    每次找 (S) 最小的后缀 (S[i:]),则在 (S[:i]) 的 Lyndon 分解后面加上一项 (S[i:]) 就是答案。


    设原字符串为 (S) ,逐个加入字符,我们需要维护扫描的左端点 (l),右端点 (r) 和当前区间 ([l,r]) 的 Lyndon 周期 (d)

    (s[r]<s[r-d]) 时,当前的近似 Lyndon 串即将结束,我们需要把它开头的那些完整的 Lyndon 串切下来,并且把最后剩余的一段重新处理,即令 (r=l+1,d=1)

    (s[r]>s[r-d]) 时,当前近似 Lyndon 串成为一个 Lyndon 串(它的 Lyndon 周期增大了),故 (d=r-l+1)

    (s[r]=s[r-d]) 时,新字符只是当前近似 Lyndon 串的延伸。

    #include <bits/stdc++.h>
    using namespace std;
    string s;
    signed main()
    {
        cin>>s;
        int l=0,r=1,d=1;
        s+='';
        while(s[l])
        {
            if(s[r]<s[r-d])
            {
                while(l+d<=r) l+=d, cout<<l<<" ";
                r=l,d=1;
            }
            else if(s[r]>s[r-d])
            {
                d=r-l+1;
            }
            ++r;
        }
    }
    
  • 相关阅读:
    Tomcat5配置mysql
    Eclipse完全手册
    MBR是什么
    必杀技公布——用特征码定位关键代码,秒杀MFC程序
    Google C++编程命名约定
    认识硬盘主引导扇区
    c++ const 用法详解
    主引导区
    C++ 关于struce结构体字节对齐
    Fedora 显示设备配置工具介绍
  • 原文地址:https://www.cnblogs.com/mollnn/p/13671337.html
Copyright © 2011-2022 走看看