zoukankan      html  css  js  c++  java
  • 石环

    1699:石环

    时间限制: 1000 ms         内存限制: 262144 KB
    【题目描述】

    桌子上有 n个石头围成一个环。
    每个石头都有一种颜色。每种颜色可以用不同的小写英文字母表示,所以总共有26种颜色。不同的石头可能有相同的颜色。
    如果每一对相邻的石头都是不同颜色的,则称这n个石头构成的环是美丽的。
    两个石头是相邻的充要条件是这两个石头中间没有其他石头。
    例如:1号和 2号是相邻的,2号和3号是相邻的,…,n号和1号是相邻的。
    现在,你可以从这 n 个石头中拿走一段连续的石头(可以为空),且你只能拿一次。
    你的任务是对于每个k(0≤k≤n-1),判断是否存在一种取石头的方案,使得在拿走k个连续的石头后,剩下的n-k个石头构成的环是美丽的。
    【输入】

    输入包含多组测试数据,以EOF结束。

    每组数据有一行字符串s,字符串第i位表示桌上第i个石头的颜色。设字符串s的长度为n,则1≤n≤106。字符串只包含小写英文字母。
    【输出】

    对于每组数据,按照样例的格式输出数据编号和一个长度为n
    的字符串。如果存在一种取石头的方案,使得在拿走k个连续的石头后,剩下的n-k个石头构成的环是美丽的,则字符串的第k位(由0开始编号)为1,否则为0。
    【输入样例】

    rrg
    rrrrr
    brbg
    abab

    【输出样例】

    Case 1: 011
    Case 2: 00001
    Case 3: 1111
    Case 4: 1011

    【提示】

    【数据规模】

    对于所有数据,数据组数不超过 6组,1≤n≤1e6。

    【题解】

    破环成链

    首先发现相邻的两个相同肯定不行所以可以沿两个相邻的相同字母中间分开的到很多个子串。

    对于每个子串,它某个减去长度不美丽即是所有以剩下长度为长度的子串开头结尾都相同。

    考虑KMP求出每个nex,设该串从l到r。

    则该串开头nex[r]个和结尾的nex[r]个字符相同,所以对于该子串,不能剩下(r+1-nex[r])个字符。

    继续考虑hu=nex[nex[r]],同理不能剩下(r+1-hu)个字符。

    当所有分出来的子串都不能剩下i个字符时,不能删掉n-i个字符。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e6+5;
    char c[N];
    int n,pre,nex[N],cf[N],ans[N],du,t;
    inline void solve(int co,int dao)
    {
        int j=co-1;nex[co]=co-1;
        for(int i=co+1;i<=dao;i++)
        {
            while(j!=co-1&&c[j+1]!=c[i]) j=nex[j];
            if(c[j+1]==c[i]) j++;
            nex[i]=j;
        }
        int hu=nex[dao],cj=dao-co+1;
        while(hu!=co-1)
        {
            ans[dao-hu+1]--;
            hu=nex[hu];
        }
        for(int i=1;i<=cj;i++) ans[i]++;
        du++;
    }
    int main()
    {
        while(~scanf("%s",c+1))
        {
            memset(cf,0,sizeof(cf));
            memset(ans,0,sizeof(ans));
            memset(nex,0,sizeof(nex));
            n=strlen(c+1);pre=1;du=0;
            for(int i=1;i<=n;i++) c[i+n]=c[i];
            for(int i=2;i<=2*n;i++)
            {
                if(c[i]==c[i-1])
                {
                    solve(pre,i-1);
                    pre=i;
                }
            }
            solve(pre,n*2);
            cout<<"Case "<<++t<<": ";
            for(int i=0;i<=n-1;i++)
            {
                if(ans[n-i]) cout<<"1";
                else cout<<"0"; 
            }
            cout<<"
    ";
        }
    }
  • 相关阅读:
    要学习TINY框架要有什么前提条件?
    如何获取最新的代码?
    python 反射的用法
    面试题1
    Process多进程的创建方法
    异常捕捉
    用type动态创建Form
    ModelForm的使用
    git 常见命令
    TVTK库的安装
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12146690.html
Copyright © 2011-2022 走看看