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;
        }
    }
    
  • 相关阅读:
    设计模式的分类
    SQL Server 2005 TSQL 学习笔记:排名函数
    JS正则表达式语法
    魅族 “拜产品教”公司的优秀与局限
    jqueryMobile初始化组件
    Loading Scripts Without Blocking
    LabJs学习笔记:分析图
    翻转的css3样式
    IE(IE6/IE7/IE8)支持HTML5标签
    我的空间轨迹!
  • 原文地址:https://www.cnblogs.com/mollnn/p/13671337.html
Copyright © 2011-2022 走看看