zoukankan      html  css  js  c++  java
  • UESTC_Ferris Wheel String 2015 UESTC Training for Search Algorithm & String<Problem L>

    L - Ferris Wheel String

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 43000/43000KB (Java/Others)
     

    title

    Have you ever been to London?

    Our Master Qiu will tell you how amazing in London and how funny a Ferris Wheel String is.

    One day, while our Master Qiu was recovering Great Britain, he was thinking about an interesting problem about string. In front of him, a London Ferris Wheel was revolving. There were some seats on the large Ferris Wheel. However, in Master Qiu's mind, each seat was a lower-case letter so that the Ferris Wheel was a beautiful string that was revolving all the time. Let's call it Ferris Wheel String.

    In the revolving operation, you can put several front letters to the last of the string. Of course, you can also put all the letters to the last, so you will get the string itself. For example, you can change string abcd into 4 strings, such as bcdacdabdabcabcd. Obviously, in the revolving operation, a string of length n can be changed into n strings.

    Master Qiu found out an interesting phenomenon that the Ferris Wheel String spent exactly one second revolving one letter. For example, at the beginning(0 second),the Ferris Wheel String was abcd,after one second,it became bcda ... and after four seconds, it became abcd.

    Master Qiu is a Romantic guy. He thought after exactly K second(s), the Ferris Wheel String became extremely beautiful.

    Now, he would like to ask you a question:

    After exactly K second(s), among the n strings obtained by revolving a string of length n, how many distinct strings are lexicographically smaller than the beautiful string, how many distinctstrings are lexicographically equal to the beautiful string and how many distinct strings are lexicographically bigger than the beautiful string ?

    (If you really can not understand Master Qiu's mind, see examples and Hint)

    Input

    The first line contains a string of length n1n2105 and the second line contains an integer k1kn.

    The string only contains lower-case letters.

    Output

    Output three integers separated by two spaces that are your answer to Master Qiu. Do not output anything after the last integer.

    Sample input and output

    Sample InputSample Output
    abcabc
    1
    1 1 1
    aaaaaaa
    3
    0 1 0
    himverihimverihimveri
    18
    0 1 6
    lvhqsjtdgckrznjsbargcojiyuf
    19
    7 1 19
    abbabaabbaababbabaababbaabbaba
    29
    3 1 26

    Hint

    Let's define that < means lexicographically smaller,> means lexicographically bigger and = means lexicographically equal.
    Also, ans1 means the number of strings < bcabca,ans2 means the number of strings = bcabca and ans3 means the number of strings > bacabca.
    Explain for lexicography :
    Let's only consider lexicographical order between two strings when |S|=|T|.
    If S<T, there exits a position p (0p<|S|) satisfying that Si=Ti when 0i<p but Sp<Tp.
    If S>T, there exits a position p (0p<|S|) satisfying that Si=Ti when 0i<p but Sp>Tp.
    If S=T, then Si=Ti for all i (0i<|S|)
    And we all know that a<b<c<  <x<y<z.
    Explain for the first example :
    The Ferris Wheel String is abcabc and K=1 , so that the beautiful string is bcabca
    After 1 second, it becomes cabcab, cabcab>bcabca;ans3+=1;
    After 2 seconds, it becomes abcabc, abcabc<bcabca;ans1+=1;
    After 3 seconds, it becomes bcabca, bcabca=bcabca;ans2+=1;
    After 4 seconds, it becomes cabcab. But it has appeared. So, do not count it.
    After 5 seconds, it becomes abcabc. But it has appeared. So, do not count it.
    After 6 seconds, it becomes bcabca. But it has appeared. So, do not count it.
    Therefore, ans1=1, ans2=1 and ans3=1.

    Use double hash rather than single hash if you wanna hash.

    解题报告:

     首先我们将移动后的字符串 * 2处理出来,之后Hash处理,注意使用双哈希.

     相同字符换的判断我们将字符串本身的哈希值再哈希即可..

     那么字典序如何判断呢?

     我们考虑字典序时,前面一段都是一样的,之后在某个位置就不同了,满足二分性质,因此我们通过二分来找到第一个不一样的位置,从而比较字典序的大小

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    typedef long long ll;
    using namespace std;
    const int maxn = 2e5 + 500 , p1 = 2807303 , mod1 = 1e9 + 7 , p2 = 5614657 , mod2 = 1e9 + 9, MaxHashSize = 1403641 , MaxStatusSize = 2e5 + 500;
    char str[maxn*2],temp[maxn];
    int k,len,stdhash1,stdhash2,head[MaxHashSize],next_new[MaxStatusSize],size = 0;
    ll hash1[maxn*2],fac1[maxn+50],hash2[maxn*2],fac2[maxn+50];
    typedef struct status
    {
     int hash1,hash2;    
    };
    
    status st[MaxStatusSize];
    
    
    int gethashvalue(int l,int r,int id)
    {
       ll ans;
       if (id == 1)
        {
           ans = (hash1[r] - hash1[l-1]*fac1[r-l+1])%mod1;
           if (ans < 0)
            ans += mod1;
           return ans;
        }
       else
        {
           ans = (hash2[r] - hash2[l-1]*fac2[r-l+1])%mod2;
           if (ans < 0)
            ans += mod2;
           return ans;
        }
    }
    
    void init_hash()
    {
       memset(head,-1,sizeof(head));
       hash1[0] = 0,hash2[0] = 0;
       for(int i = 1 ; i <= 2*len ; ++ i )
        hash1[i] = (hash1[i-1]*p1 + str[i]) % mod1;
       for(int i = 1 ; i <= 2*len ; ++ i )
        hash2[i] = (hash2[i-1]*p2 + str[i]) % mod2;
       fac1[0] = 1;
       for(int i = 1 ; i <= maxn ; ++ i)
        fac1[i] = (fac1[i-1]*p1) % mod1;
       fac2[0] = 1;
       for(int i = 1 ; i <= maxn ; ++ i)
        fac2[i] = (fac2[i-1]*p2) % mod2;
    }
    
    int HashValue(const status &x)
    {
       return (x.hash1 + x.hash2) % MaxHashSize;
    }
    
    bool insert(int id)
    {
      int val = HashValue(st[id]);
      int u = head[val];
      while(u != -1)
       {
             if (!memcmp(&st[u],&st[id],sizeof(status)))
              return false;
             u = next_new[u];
       }
      next_new[id] = head[val];
      head[val] = id;
      return true;
    }
    
    
    void dump(int l,int r)
    {
       for(int i = l ; i <= r ; ++ i)
        printf("%c",str[i]);
       printf("
    ");
    }
    
    int main(int argc,char *argv[])
    {
      scanf("%s%d",str+1,&k);len = strlen(str+1);
      memcpy(temp,str+1,k);memcpy(str+1,str+k+1,len-k);memcpy(str+len-k+1,temp,k);memcpy(str+len+1,str+1,len);init_hash();
      stdhash1 = gethashvalue(1,len,1);
      stdhash2 = gethashvalue(1,len,2);
      ll ans1 = 0 , ans2 = 0 , ans3 = 0 ; // <  =   >
      for(int i = 2 ; i <= len+1 ; ++ i)
       {
             st[size].hash1 = gethashvalue(i,i+len-1,1);
             st[size].hash2 = gethashvalue(i,i+len-1,2);
             if (!insert(size))
              {
                    //dump(i,i+len-1);
                    continue;
           }
             int thishash1 = st[size].hash1;
             int thishash2 = st[size++].hash2;
             if (thishash1 == stdhash1 && thishash2 == stdhash2)
              {
                    ans2 ++ ;
                    continue;
            }
           if (str[i] != str[1])
            {
                  if (str[i] < str[1])
                   ans1++;
                  else
                   ans3++;
                  continue;
           }
          int l = 1 , r = len-1;
          while(l < r)
           {
                 int mid = l + (r-l+1)/2;
                 int stdh1 = gethashvalue(1,mid,1);
                 int stdh2 = gethashvalue(1,mid,2);
                 int thish1 = gethashvalue(i,i+mid-1,1);
                 int thish2 = gethashvalue(i,i+mid-1,2);
                 if (stdh1 == thish1 && stdh2 == thish2)
                  l = mid;
                 else
                  r = mid - 1;
           }
          if (str[i + l] < str[1 + l])
           ans1++;
          else
           ans3++;
       }
      printf("%lld %lld %lld
    ",ans1,ans2,ans3);
      return 0;
    }
    No Pain , No Gain.
  • 相关阅读:
    Oracle忘记用户名和密码以及管理员用户新增修改删除用户
    Oracle11.2安装和完全卸载及卸载后重装等问题
    软件测试之路2
    软件测试之路1
    Git入门笔记
    CentOS 6.5下二进制安装 MySQL 5.6
    十款压力测试工具
    tomcat 内存设置
    tomcat 安全
    tomcat 模式详解
  • 原文地址:https://www.cnblogs.com/Xiper/p/4499181.html
Copyright © 2011-2022 走看看