• HDU 3374 String Problem(最大最小表示+KMP)题解


    题意:给你一个字符串,这个字符串可以这样操作:把第一个字符放到最后一个形成一个新的字符串,记原式Rank为1,每操作一步Rank+1,问你这样操作得出的最小字典序的字符串的Rank和这样的字符串有几个,最大字典序的字符串的Rank和这样的字符串有几个。

    思路:手动模拟操作复杂度O(n^2)果断超时,引入一种专门计算此情况的方法,复杂度O(n)。

    这里只说最小表示:

    我们先拿两个指针i,j,分别指向s[0],s[1],将k初始化为0。然后我们循环计算s[i + k]是否等于s[j + k],直到找到一个不等的情况;如果找不到,说明当前已经是最小了。当不相等时,有两种情况:

    1.s[i + k]>s[j + k]说明以s[j + k]为开头字典序更小,i移动到该位置,置k = 0

    2.s[i + k]<s[j + k]说明s[j]开头不行,j移动到j + k + 1,置k = 0

    最后返回min(i,j)

    算几个字符串可以用KMP的next数组计算最小循环节解决。

    #include<iostream>
    #include<algorithm>
    const int maxn = 1000000+5;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    int fail[maxn];
    char s[maxn],tmp[maxn];
    void getFail(char *p){
         fail[0] = -1;
         int j = 0,k = -1;
         int len = strlen(p);
         while(j < len){
            if(k == -1 || p[j] == p[k]){
                fail[++j] = ++k;
            }
            else{
                k = fail[k];
            }
         }
    }
    int KMP(char *t,char *p){
        getFail(p);
        int i = 0,j = 0;
        int lent = strlen(t),lenp = strlen(p);
        while(i < lent){
            if(j == -1 || t[i] == p[j]){
                i++;
                j++;
                if(j == lenp) return 1;
            }
            else{
                j = fail[j];
            }
        }
        return 0;
    }
    int get_min(char *p){
        int len = strlen(p);
        int i = 0,j = 1,k = 0;
        while(i < len && j <len && k < len){
            int t = s[(i + k)%len] - s[(j + k)%len];
            if(t == 0) k++;
            else{
                if(t > 0)
                    i += k + 1;
                else
                    j += k + 1;
                if(i == j) j++;
                k = 0;
            }
        }
        return min(i,j);
    }
    int get_max(char *p){
        int len = strlen(p);
        int i = 0,j = 1,k = 0;
        while(i < len && j <len && k < len){
            int t = s[(i + k)%len] - s[(j + k)%len];
            if(t == 0) k++;
            else{
                if(t > 0)
                    j += k + 1;
                else
                    i += k + 1;
                if(i == j) j++;
                k = 0;
            }
        }
        return min(i,j);
    }
    int main(){
        while(scanf("%s",s) != EOF){
            int len = strlen(s);
            int MIN = get_min(s);
            int MAX = get_max(s);
            for(int i = 0,j = MIN;i < len;i++,j++){
                tmp[i] = s[j % len];
            }
            tmp[len] = '';
            getFail(tmp);
            int c = len - fail[len],ans;
            if(len % c == 0) ans = len / c;
            else ans = 1;
            printf("%d %d ",MIN + 1,ans);
            for(int i = 0,j = MAX;i < len;i++,j++){
                tmp[i] = s[j % len];
            }
            tmp[len] = '';
            getFail(tmp);
            c = len - fail[len];
            if(len % c == 0) ans = len / c;
            else ans = 1;
            printf("%d %d
    ",MAX + 1,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    bzoj 3594: [Scoi2014]方伯伯的玉米田
    普通平衡树(指针splay)
    codeforces 475D. CGCDSSQ
    php 购物车功能
    PHP现阶段发现的不足点
    php 多维数据根据某个或多个字段排序
    redis可视化辅助工具
    Redis在window下安装以及配置
    hive数据操作
    hive 表分区操作
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9408763.html
Copyright © 2020-2023  润新知