zoukankan      html  css  js  c++  java
  • [BZOJ3790] 神奇项链

    Description

    两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。给定一个字符串,询问你需要使用第二个机器多少次才能生成这个特殊的字符串。

    Solution

    首先我们用 Manacher 处理出每个位置为中心的最长回文半径 (p_i),并计算出 (l_i)(首先对任意 (i),令 (l[i+p_i-1] leftarrow p_i),然后从左往右扫一遍 (l[i]=max(l[i],l[i-2]-2))

    预处理出一个前缀中的所有起点可以到达的最远位置 (g[i]=max(g[i-1],i+l[i]-1))

    考虑贪心,假设当前已经生成了长度为 (i) 的前缀,则下一次跳到 (g[i+1]) 即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    
    int l[N],n,T,g[N];
    
    namespace man {
    const int N = 2100005;
    char str[N], s[N<<1];
    int a[N<<1];
    
    int manacher(int len){
        a[0] = 0;
        int ans = 0, j;
        for(int i = 0; i < len; ){
            while(i-a[i]>0 && s[i+a[i]+1]==s[i-a[i]-1])
                  a[i]++;
            if(ans < a[i])ans = a[i];
            j = i+1;
            while(j<=i+a[i] && i-a[i]!=i+i-j-a[i+i-j]){
                a[j] = min(a[i+i-j], i+a[i]-j);
                j++;
            }
            a[j] = max(i+a[i]-j, 0ll);
            i = j;
        }
        for(int i=0;i<len;i++) l[i]=0;
        for(int i=0;i<len;i++) l[i-a[i]+1]=max(l[i-a[i]+1],a[i]);
        for(int i=0;i<len;i++) l[i]=max(l[i],l[i-2]-2);
        for(int i=1;i<=len;i++) l[i]=l[i*2-1];
        for(int i=0;i<len;i++) str[i]='';
        return ans;
    }
    
    int solve(){
        int len;
        len = 2*strlen(str)+1;
        for(int i = 0; str[i] != ''; i++){
            s[i+i] = '';
            s[i+i+1] = str[i];
        }
        s[len-1] = '';
        return manacher(len);
    }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        string s;
        while(cin>>s)
        {
            n=s.length();
            for(int i=0;i<n;i++)
            {
                man::str[i]=s[i];
            }
            man::solve();
            for(int i=1;i<=n;i++) g[i]=0;
            for(int i=1;i<=n;i++) g[i]=max(g[i-1],i+l[i]-1);
            int pos=0,ans=0;
            while(pos<n)
            {
                pos=g[pos+1];
                ans++;
            }
            cout<<ans-1<<endl;
        }
    }
    
    
  • 相关阅读:
    POJ2778 DNA Sequence AC自动机上dp
    codeforces732F Tourist Reform 边双联通分量
    codeforces786B Legacy 线段树优化建图
    洛谷P3588 PUS 线段树优化建图
    codeforces1301D Time to Run 模拟
    codeforces1303B National Project 二分或直接计算
    codeforces1303C Perfect Keyboard 模拟或判断欧拉路
    codeforces1303D Fill The Bag 二进制应用+贪心
    python之路——使用python操作mysql数据库
    python之路——mysql索引原理
  • 原文地址:https://www.cnblogs.com/mollnn/p/13281286.html
Copyright © 2011-2022 走看看