zoukankan      html  css  js  c++  java
  • hdu5442 Favorite Donut

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5442

    题目大意:给你一个长度为n的字符串,将它首尾相连成环。问你这个环上找一个长度为n的字典序最大的串(你可以沿顺时针或逆时针找),如果有多个这样的串,输出首字母标号最小的,如果还有多个,输出顺时针的

    解:

    1、最小表示法解(时间复杂度:O(n))

    最小表示法~

    2、后缀数组(时间复杂度:O(logn))

    比赛的时候想到的方法,然而并没有写出来,不好写+高时间复杂度=不推荐

    最小表示法:

     1 /*
     2  * Problem:  
     3  * Author:  SHJWUDP
     4  * Created Time:  2015/9/16 星期三 16:18:36
     5  * File Name: 1001.cpp
     6  * State: 
     7  * Memo: 
     8  */
     9 #include <iostream>
    10 #include <cstdio>
    11 #include <vector>
    12 #include <cstring>
    13 #include <algorithm>
    14 
    15 using namespace std;
    16 
    17 struct KMP {
    18     int n;
    19     string T;    //target string
    20     vector<int> nt;
    21     KMP(const char * _str) {
    22         n=strlen(_str);
    23         T.assign(_str, _str+n);
    24         getFail();
    25     }
    26     void getFail() {
    27         nt.resize(n+1);
    28         nt[0]=-1;
    29         for(int i=0, j=-1; i<n; ) {
    30             if(j==-1 || T[i]==T[j]) {
    31                 nt[++i]=++j;
    32             } else j=nt[j];
    33         }
    34     }
    35     int match(const char * P) {//pattern string
    36         //在P中找T
    37         int ret=-1;
    38         for(int i=0, j=0; P[i]; ) {
    39             if(j==-1 || P[i]==T[j]) {
    40                 ++i;
    41                 if(++j==n) {
    42                     if(P[i]) ret=i-n;
    43                 }
    44             } else j=nt[j];
    45         }
    46         return ret;
    47     }
    48 };
    49 
    50 int maximum_representation(const char * s) {
    51     int i, j, k, len=strlen(s);
    52     for(i=0, j=1, k=0; i<len && j<len && k<len; ) {
    53         int tmp=s[(i+k)%len]-s[(j+k)%len];
    54         if(tmp==0) ++k;
    55         else {
    56             if(tmp>0) j+=k+1;//改成小于号是最小表示法
    57             else i+=k+1;
    58             if(i==j) ++j;
    59             k=0;
    60         }
    61     }
    62     return min(i, j);
    63 }
    64 
    65 int n;
    66 int main() {
    67 #ifndef ONLINE_JUDGE
    68     freopen("in", "r", stdin);
    69     //freopen("out", "w", stdout);
    70 #endif
    71     int T;
    72     scanf("%d", &T);
    73     while(T--) {
    74         scanf("%d", &n);
    75         string str1;
    76         cin>>str1;
    77         int pos1=maximum_representation(str1.c_str());
    78         string str2(str1.rbegin(), str1.rend());
    79         int pos2=maximum_representation(str2.c_str());
    80         str1+=str1;
    81         str2+=str2;
    82         KMP kmp(str2.substr(pos2, n).c_str());
    83         pos2=kmp.match(str2.c_str());
    84         auto cmp=[&]()->bool {
    85             for(int i=0; i<n; ++i) {
    86                 if(str1[pos1+i]!=str2[pos2+i])
    87                     return str1[pos1+i]>str2[pos2+i];
    88             }
    89             return pos1<=n-pos2-1;
    90         };
    91         if(cmp()) {
    92             printf("%d 0
    ", pos1+1);
    93         } else {
    94             printf("%d 1
    ", n-pos2);
    95         }
    96     }
    97     return 0;
    98 }
    View Code

    后缀数组:

      1 /*
      2  * Problem:  
      3  * Author:  SHJWUDP
      4  * Created Time:  2015/9/14 星期一 16:06:34
      5  * File Name: 1001.cpp
      6  * State: 
      7  * Memo: 
      8  */
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <vector>
     12 #include <cstring>
     13 #include <algorithm>
     14 
     15 using namespace std;
     16 
     17 struct SuffixArray {
     18     static const int SIGMA_SIZE=256;
     19     int n;//串长+1
     20     vector<int> str;//str中最后一个元素为0
     21     vector<int> sa;//第i大后缀为str[sa[i]:]
     22     vector<int> rank;//str坐标为i的后缀的字典序排名
     23     vector<int> height;//sa[i-1]和sa[i]的最长公共前缀(LCP)
     24     SuffixArray(const char * _str) {
     25         n=strlen(_str)+1;
     26         str.resize(n);
     27         for(int i=0; i<n; ++i) str[i]=_str[i];
     28         build_sa();
     29     }
     30     void build_sa(int m=SIGMA_SIZE) {
     31         sa.assign(n, 0);
     32         vector<int> x(n, 0), y(n, 0), c(m, 0);//c(字符计数)
     33         //x[i]:str坐标为i的x值rank
     34         //y[i]:y值第i大的str坐标
     35         //*y数组中前k个为y段串不足k长度的串对应str坐标
     36         for(int i=0; i<n; ++i) ++c[x[i]=str[i]];
     37         for(int i=1; i<m; ++i) c[i]+=c[i-1];
     38         for(int i=n-1; i>=0; --i) sa[--c[x[i]]]=i;
     39         for(int k=1; k<=n; k<<=1) {
     40             int p=0;
     41             //直接利用sa数组排序第二关键字
     42             for(int i=n-k; i<n; ++i) y[p++]=i;
     43             for(int i=0; i<n; ++i) if(sa[i]>=k) y[p++]=sa[i]-k;
     44             //基数排序第一关键字
     45             c.assign(m, 0);
     46             for(int i=0; i<n; ++i) ++c[x[y[i]]];
     47             for(int i=1; i<m; ++i) c[i]+=c[i-1];
     48             for(int i=n-1; i>=0; --i) sa[--c[x[y[i]]]]=y[i];
     49             //根据sa和y数组计算新的x数组
     50             swap(x, y);
     51             p=1; x[sa[0]]=0;
     52             for(int i=1; i<n; ++i) {
     53                 x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
     54             }
     55             if(p >= n)break;
     56             m = p;//下次基数排序的最大值
     57         }
     58         getHeight();
     59     }
     60     void getHeight() {
     61         rank.resize(n);
     62         height.resize(n);
     63         for(int i=1; i<n; ++i) rank[sa[i]]=i;
     64         for(int i=0, k=0; i<n-1; ++i) {
     65             //h[i]=height[rank[i]]
     66             if(k) --k;    //h[i]>=h[i-1]-1
     67             int j=sa[rank[i]-1];
     68             while(str[i+k]==str[j+k]) ++k;
     69             height[rank[i]]=k;
     70         }
     71     }
     72 };
     73 
     74 int n;
     75 bool cmp(string a, string b, int x, int y) {
     76     for(int i=0; i<n; ++i) {
     77         if(a[x+i]!=b[y+i]) return a[x+i]>b[y+i];
     78     }
     79     return x<=n-y-1;
     80 }
     81 int main() {
     82 #ifndef ONLINE_JUDGE
     83     freopen("in", "r", stdin);
     84     //freopen("out", "w", stdout);
     85 #endif
     86     int T;
     87     scanf("%d", &T);
     88     while(T--) {
     89         scanf("%d", &n);
     90         string str1;
     91         cin>>str1;
     92         string str2(str1.rbegin(), str1.rend());
     93         str1+=str1;
     94         str2+=str2;
     95         SuffixArray sa1(str1.c_str());
     96         int pos1;
     97         for(int i=sa1.n-1; i>=1; --i) {
     98             if(sa1.sa[i]<n) {
     99                 pos1=sa1.sa[i]; break;
    100             }
    101         }
    102         SuffixArray sa2(str2.c_str());
    103         int pos2=-1, mi=n;
    104         for(int i=sa2.n-1; i>=1; --i) {
    105             if(pos2!=-1) mi=min(mi, sa2.height[i+1]);
    106             if(mi<n) break;
    107             if(sa2.sa[i]<n) pos2=sa2.sa[i];
    108         }
    109         if(cmp(str1, str2, pos1, pos2)) {
    110             printf("%d 0
    ", pos1+1);    
    111         } else {
    112             printf("%d 1
    ", n-pos2);
    113         }
    114     }
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    Java 第十一届 蓝桥杯 省模拟赛 洁净数
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    20. Valid Parentheses
    290. Word Pattern
    205. Isomorphic Strings
    71. Simplify Path
  • 原文地址:https://www.cnblogs.com/shjwudp/p/4814172.html
Copyright © 2011-2022 走看看