P6114 【模板】Lyndon 分解

题目描述

这是一道模板题。

读入一个由小写英文字母组成的字符串 ss ,请把这个字符串分成若干部分 s=s_1s_2s_3\cdots s_ms=s1s2s3sm,使得每个 s_isi 都是 \text{Lyndon Word}Lyndon Word,且 \forall 1\le i<m:s_i\ge s_{i+1}1i<m:sisi+1。输出 s_1s1 到 s_msm 这些串长度的右端点的位置。位置编号为 11 到 nn。

一个字符串 ss 是一个 \text{Lyndon Word}Lyndon Word,当且仅当 ss 是其所有后缀中最小的字符串。

为了减小输出量,你只需要输出所有右端点的异或和。

输入格式

一行一个长度为 nn 的仅包含小写英文字母的字符串 ss。

输出格式

一行一个整数,表示所有右端点的异或和。

 

题解:https://www.luogu.com.cn/problem/solution/P6114

#include <bits/stdc++.h>
#define IO_read ios::sync_with_stdio(false);cin.tie(0)
#define fre freopen("in.txt", "r", stdin)
#define _for(i,a,b) for(int i=a; i< b; i++)
#define _rep(i,a,b) for(int i=a; i<=b; i++)
#define inf 0x3f3f3f3f
#define lowbit(a) ((a)&-(a))
using namespace std;
typedef long long ll;
template <class T>
void read(T &x)
{
    char c; bool op=0;
    while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1;
    x=c-'0';
    while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0';
    if(op) x=-x;
}
template <class T>
void write(T x)
{
    if(x<0) putchar('-'), x=-x;
    if(x>=10) write(x/10);
    putchar('0'+x%10);
}

const int maxn=5e6+5;
char s[maxn];

int main()
{
    scanf("%s", s+1);
    int n=strlen(s+1), ans=0;
    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++;
            else j=i;
            k++;
        }
        while(i<=j)
        {
            ans^=i+k-j-1;
            i+=k-j;
        }
    }
    printf("%d\n", ans);
    return 0;
}

 

 

posted @ 2020-07-29 19:56  N_Yokel  阅读(117)  评论(0编辑  收藏  举报