zoukankan      html  css  js  c++  java
  • 【BZOJ4104】解密运算(THUSC2015)-排序和循环串性质应用

    测试地址:解密运算
    题目大意:运用以下方法加密一个字符串:首先在字符串后加一个比字符集中任何字符字典序都小的字符(称为“#”),然后列出这个字符串的所有循环串,如字符串ABA#的循环串有以下四个:ABA#,BA#A,A#AB,#ABA。然后把这些循环串按照字典序从小到大排序,将最后一列的字符依次排下来形成一个新串,这就是加密后的串。给定一个加密后的串,求出原串。字符串长度N和字符集大小M200000
    做法:继续来刷THUSC2015的题……这题虽然是THUSC2015的第二题,但感觉比第一题水多了……
    这一题应该使用排序算法来解决。
    设排序后第i小的循环串的第j个字符为f(i,j),我们知道把加密后串的字符从小到大排列,就是排序后循环串的第一列的字符。我们设第一列的第i个字符原来是最后一列的第p(i)个字符,即f(1,i)=f(n+1,p(i)),由于循环串的性质,可以得出对于任意1j<n+1f(i,j+1)=f(p(i),j)。我们还知道原字符串就是f(1,2)f(1,n+1),由上面的结论,我们总能找到这些个字符所对应的第一列的字符,例如f(1,2)=f(p(1),1)f(1,3)=f(p(1),2)=f(p(p(1)),1)等等,那么我们只需要求出p,然后初始化一个指针x=p(1),重复输出f(x,1),将x赋值为p(x)这个过程,直到已经输出了N个字符为止。至于求p,就以f(i,n+1)为第一关键字,f(i,1)为第二关键字,原先的标号为第三关键字将这些东西从小到大排序,排完序后第i个标号就是p(i)。总时间复杂度为O(NlogN)
    犯二的地方:起先没有考虑到第三个关键字,惨烈WA……
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,m,a[200010];
    struct forsort {int a,b,id;} f[200010];
    
    bool cmp(int a,int b) {return a<b;}
    bool cmp2(forsort a,forsort b)
    {
      if (a.a!=b.a) return a.a<b.a;
      else if (a.b!=b.b) return a.b<b.b;
           else return a.id<b.id;
    }
    
    int main()
    {
      scanf("%d%d",&n,&m);
      for(int i=1;i<=n+1;i++)
      {
        scanf("%d",&a[i]);
        f[i].a=a[i],f[i].id=i;
      }
      sort(a+1,a+n+2,cmp);
      for(int i=1;i<=n+1;i++) f[i].b=a[i];
    
      sort(f+1,f+n+2,cmp2);
      int x=1;
      for(int i=1;i<=n;i++)
      {
        printf("%d ",f[x].b);
        x=f[x].id;
      }
    
      return 0;
    }
    
  • 相关阅读:
    软件测试人员的年终绩效考核怎么应对
    收藏
    顶踩组件 前后两版
    订阅组件
    hdu 1963 Investment 完全背包
    hdu 4939 Stupid Tower Defense 动态规划
    hdu 4405 Aeroplane chess 动态规划
    cf 414B Mashmokh and ACM 动态规划
    BUPT 202 Chocolate Machine 动态规划
    hdu 3853 LOOPS 动态规划
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793689.html
Copyright © 2011-2022 走看看