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;
        }
    }
    
    
  • 相关阅读:
    CSS3(4)---动画(animation)
    MDT 2010驱动管理新方法。
    windows 2012 试用180天
    Mac地址绑定的wifi
    用于主题检测的临时日志(b2d5c7b3-e3f6-4b0f-bfa4-a08e923eda9b
    samba4.1.9安装
    samba权限之easy举例说明--原创
    NFS性能优化
    工作组环境下管理windows.
    管理windows防火墙
  • 原文地址:https://www.cnblogs.com/mollnn/p/13281286.html
Copyright © 2011-2022 走看看