zoukankan      html  css  js  c++  java
  • CF 1560E E. Polycarp and String Transformation(思维)

    https://codeforces.com/contest/1560/problem/E

    题意:

    有一个串s和一个空串t,可以进行若干次以下操作,

    每次操作先把s拼在t的后面,然后删掉s中的一种字母

    直至s为空串

    现在给出t,还原出s以及删除字母的顺序

    原始思路:

    t串中最后一个字母就是最后删除的字母,再往前碰到的就是倒数第二次删除的字母,再往前就是倒数第三次删除的字母,……,这样可以还原删除字母的顺序

    假设字母一共有x种,最后一个删除的字母被拼接了x次,所以用这种字母在t串中的总次数除以x,就得到最后一次拼接的长度;以此类推往前,能够还原每次被拼接的串

    每次还原都有限制不可以出现的字母,如果他们出现了就无解

    但是只根据长度可能会导致顺序不符合,所以还原出的s还要按规则产生一个t,与给定的t相等才可以

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define N 500004
     
    char t[N];
     
    char s[N],a[N],ss[N];
    int sum[27][N];
     
    bool vis[27];
     
    int main()
    {
        int T,n,all,need,last,div,tmp,len,L;
        bool tag,ok;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",t+1);
            n=strlen(t+1);
            reverse(t+1,t+n+1);
            for(int i=1;i<=26;++i) 
            {
                sum[i][0]=0;
                vis[i]=false;
            }
            all=0;
            for(int i=1;i<=n;++i)
            {
                if(!vis[t[i]-'a'+1]) 
                {
                    a[++all]=t[i];
                    vis[t[i]-'a'+1]=true;
                } 
                for(int j=1;j<=26;++j) sum[j][i]=sum[j][i-1];
                sum[t[i]-'a'+1][i]++;
            }
            div=all;
            last=0;
            need=1;
            for(int i=1;i<=26;++i) vis[i]=false;
            vis[a[1]-'a'+1]=true;
            ok=true;
            for(int i=1;i<=n && need<all;++i)
            {
                tag=true;
                if(!vis[t[i]-'a'+1])
                {
                    ok=false;
                    break;
                }
                for(int j=1;j<=need && tag;++j)
                {
                    tmp=sum[a[j]-'a'+1][i]-sum[a[j]-'a'+1][last];
                    if(tmp*(all-j+1)!=sum[a[j]-'a'+1][n]) tag=false;
                }
                if(tag)
                {
                    ++need;
                    vis[a[need]-'a'+1]=true;
                    last=i;
                    div--;
                }
            }
            if(need!=all) ok=false;
            else
            {
                reverse(a+1,a+all+1);
                len=L=0;
                for(int i=n;i>last;--i) s[++len]=t[i];
                reverse(t+1,t+n+1);
                for(int i=1;i<=26;++i) vis[i]=true;
                for(int i=1;i<=all;++i)
                {
                    for(int j=1;j<=len;++j) 
                        if(vis[s[j]-'a'+1]) ss[++L]=s[j];
                    vis[a[i]-'a'+1]=false;
                }
                if(L!=n) ok=false;
                for(int i=1;i<=L && ok;++i)
                    if(ss[i]!=t[i]) ok=false; 
            }
            if(!ok) printf("-1
    ");
            else
            {
                for(int i=1;i<=len;++i) printf("%c",s[i]);
                printf(" ");
                for(int i=1;i<=all;++i) printf("%c",a[i]); 
                printf("
    ");
            }
        }
    }
    View Code

    做麻烦了

    t串中,以每个字母的最后出现位置从小到大排序,排序结果就是字母的删除顺序

    然后就可以知道每个字母被拼接多少次,根据出现总次数判断拼接次数是否合法,同时得到s串长度

    最后用s按规则产生一个t,判断与给定的t是否一样

    不需要还原每次被拼接的串

    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    SQL Server OPENQUERY使用
    VS2013程序打包报 ISEXP : error -****: An error occurred streaming
    IIS重新注册
    c#之反射(Reflection)
    c#之Lambda表达式
    c#之委托事件(DelegateEvent)
    c#之委托详解(Delegate)
    git将文件托管到github上遇到的问题
    c#之泛型详解(Generic)
    linux下操作memcache的操作命令
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15216522.html
Copyright © 2011-2022 走看看