zoukankan      html  css  js  c++  java
  • HDU 3374 最小/大表示法+KMP

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

    题意:给定一个串s,该串有strlen(s)个循环同构串,要求输出字典序最小的同构串的下标,字典序最小的出现次数,最大的同构串的下标,字典中最大的出现次数。

    思路:对于求循环同构的字典序最小可以用最小表示法求得,最大也是一样。然后设ds为字符串s+s。然后就可以用KMP求最小串在ds出现的次数和最大串出现的次数了。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<set>
    using namespace std;
    const int MAXN = 1000000 + 5;
    typedef long long int LL;
    #define INF 0x3f3f3f3f
    int Representation(char *s,int l,bool flag){ //flag:0 最小表示法  flag:1 最大表示法
        int i = 0, j = 1, k = 0;
        while (i < l&&j < l&&k < l){
            int li, lj;
            li = (i + k) >= l ? i + k - l : i + k;
            lj = (j + k) >= l ? j + k - l : j + k;
            if (s[li] == s[lj]){
                k++;
            }
            else{
                if (!flag){
                    if (s[li]>s[lj]){
                        i = i + k + 1;
                    }
                    else{
                        j = j + k + 1;
                    }
                }
                else{
                    if (s[li]<s[lj]){
                        i = i + k + 1;
                    }
                    else{
                        j = j + k + 1;
                    }
                }
                if (i == j){
                    j++;
                }
                k = 0;
            }
        }
        return i < j ? i : j;
    }
    int Next[MAXN];
    void getnext(char *s,int lens){ //KMP的next数组
        int j, k;
        j = 0; k = -1; Next[0] = -1;
        while (j < lens){
            if (k == -1 || s[j] == s[k]){
                Next[++j] = ++k;
            }
            else{
                k = Next[k];
            }
        }
    }
    int KMP_Count(char *s,int lens,char *t,int lent){ //计算t串在s串中出现的次数
        int ans = 0, j = 0;
        memset(Next, 0, sizeof(Next));
        getnext(t,lent);
        for (int i = 0; i < lens; i++){
            while (j>0 && s[i] != t[j]){
                j = Next[j];
            }
            if (s[i] == t[j]){
                j++;
            }
            if (j == lent){
                ans++;
                j = Next[j];
            }
        }
        return ans;
    }
    char str[MAXN], dstr[MAXN*2],minstr[MAXN],maxstr[MAXN];
    //原串,原串*2后的串,字典序最小的串,字典序最大的串
    int main()
    {
        while (~scanf("%s", str)){
            int len = strlen(str);
            for (int i = 0; i < len * 2 ; i++){
                dstr[i] = str[(i%len)];
            }
            //计算最小
            int minstart = Representation(str, len,0);
            for (int i = 0; i < len; i++){
                minstr[i] = str[(i + minstart) % len];
            }
            int mincount = KMP_Count(dstr, len * 2 - 1, minstr, len);
            //计算最大
            int maxstart = Representation(str, len,1);
            for (int i = 0; i < len; i++){
                maxstr[i] = str[(i + maxstart) % len];
            }
            int maxcount = KMP_Count(dstr, len * 2 - 1, maxstr, len);
            printf("%d %d %d %d
    ", minstart + 1,mincount , maxstart + 1, maxcount);
        }
        return 0;
    }
  • 相关阅读:
    《生命3.0—在亿年的尺度下审视生命的演进》阅读笔记3
    软件杯赛题周总结(2)
    《生命3.0—在亿年的尺度下审视生命的演进》阅读笔记2
    记一次阅读源码的小经历
    11
    解决在 CSS 中,如何实现动态吸顶的样式/效果 ?
    Angular 初始化项目后,如何把默认的 .css 文件修改为 .scss 文件?
    解决 Angular 项目中,添加 <router-outlet> 标签后,报错: ‘router-outlet’ is not a known element 的问题。
    在 Angular 项目中,如何为项目单独创建路由文件?
    [NOIP2013 提高组] 《火柴排队》
  • 原文地址:https://www.cnblogs.com/kirito520/p/5608981.html
Copyright © 2011-2022 走看看