CF1560 E. Polycarp and String Transformation(思维 枚举)

简介: CF1560 E. Polycarp and String Transformation(思维 枚举)

E. Polycarp and String Transformation

点击跳转

题意:

假设有一个字符串s,字符串t开始为空;

每次执行一个过程,第一步是另t = t + s,第二步是删去s中的全部的某字母。

重复执行两个步骤,直到s为空。

现在给出t串,输出s串和对应的字母删除顺序。

思路:

记录每个字符出现的最后位置,最后删除的字母,出现的最后位置越大。以此为排序标准,可以得到删除的字符顺序;

这样就得到了每个字母是第几个被删除的,记作p o s i

如何确定s的长度呢?

对于任意一个字母x来说,出现次数c n t i除以p o s i就是s中该字母的出现次数t o t。

因为在该字母x被删除前,每个过程出现的次数都是t o t;在该字母x被删除后,每个过程出现的次数都是0

所以如果c n t i % p o s i ! = 0的话,一定不是合法的t串,也就无法还原除s,输出− 1;

这样枚举一遍每个字母就能得到s的长度l e n了,只需要截取t tt中l e n长度的前缀就是s了;

上面只是检验了出现字母的个数,还没有检验具体的顺序;

如果从s能够再得到t,才说明s是合法的答案,所以要再c h e c k遍。

代码:

int cnt[30];//表示每个字母的出现次数
int las[30];//表示每个字母最后一次出现的位置 
int pos[30];///表示每个字母是第几个被删除的 
bool cmp(char a,char b){//删除字符排序的话肯定是出现位置下标越大说明删除的越晚 
  return las[a-'a']<las[b-'a'];
}
int main(){
  int _=read;
  while(_--){
    string t;cin>>t;
    memset(las,-1,sizeof las);//初始化 
    memset(cnt,0,sizeof cnt);//清空 
    for(int i=0;t[i];i++){
      int x=t[i]-'a';
      cnt[x]++;//记录每个字母出现的次数 
      las[x]=i;//更新每个字母的最大下标位置 
    }
    string del="";
    for(int i=0;i<26;i++){
      if(las[i]!=-1) del+='a'+i;//出现过的字母都删除 
    }
    sort(del.begin(),del.end(),cmp);//排序 
    memset(pos,0,sizeof pos);
    for(int i=0;i<del.size();i++){
      pos[del[i]-'a']=i+1;//记录是第几个被删的 
    }
    int len=0,flag=1;
    for(int i=0;i<26;i++){
      if(cnt[i]==0) continue;
      if(cnt[i]%pos[i]){//不整除的话不符合题意 
        flag=0;
        break;
      }
      len=len+cnt[i]/pos[i];//记录这个字母在s中的次数 
    }
    string s=t.substr(0,len);//s 
    string tmp="";//从s倒推一遍看是否和t相同 
    for(int i=1;i<=del.size();i++){
      for(int j=0;j<len;j++){
        if(pos[s[j]-'a']>=i){//删除时间>=i说明该字母还没有被删除 
          tmp+=s[j];
        }
      }
    }
    if(tmp!=t) flag=0;
    if(flag) cout<<s<<" "<<del<<endl;
    else puts("-1");  
  } 
  return 0;
}
目录
相关文章
|
图形学
unity将object[]或者string对象转换成枚举enum
unity将object[]或者string对象转换成枚举enum protected override void OnSetData(params object[] datas) { string str = datas[0].
2042 0
|
2月前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
38 0
java基础(13)String类
|
1月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
55 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
28天前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
24 2
|
30天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
1月前
|
数据可视化 Java
让星星月亮告诉你,通过反射创建类的实例对象,并通过Unsafe theUnsafe来修改实例对象的私有的String类型的成员属性的值
本文介绍了如何使用 Unsafe 类通过反射机制修改对象的私有属性值。主要包括: 1. 获取 Unsafe 的 theUnsafe 属性:通过反射获取 Unsafe类的私有静态属性theUnsafe,并放开其访问权限,以便后续操作 2. 利用反射创建 User 类的实例对象:通过反射创建User类的实例对象,并定义预期值 3. 利用反射获取实例对象的name属性并修改:通过反射获取 User类实例对象的私有属性name,使用 Unsafe`的compareAndSwapObject方法直接在内存地址上修改属性值 核心代码展示了详细的步骤和逻辑,确保了对私有属性的修改不受 JVM 访问权限的限制
50 4
|
2月前
|
安全 Java
String类-知识回顾①
这篇文章回顾了Java中String类的相关知识点,包括`==`操作符和`equals()`方法的区别、String类对象的不可变性及其好处、String常量池的概念,以及String对象的加法操作。文章通过代码示例详细解释了这些概念,并探讨了使用String常量池时的一些行为。
String类-知识回顾①

热门文章

最新文章