题意:

      给你一个最长100W的串,然后让你找到最小同构子串,还有最大同构子串的下标,最小同构子串就是把字符串连接成一个环,然后选择一个地方断开,得到的一个ASCII最小的子串(求最大同理),得到两个下标之后还要求两个数,就是最小子串出现的次数,还有最大子串出现的次数,就是所有循环移位后的到的len个子串中最小子串出现了多少次?

思路:

      求最小和最大小标这个可以用最小表示法来求(求最大就是把最小表示法稍微改一下),而求出现次数可以用KMP来求,出现次数等于最大周期数,为什么等于这个可以这样想

abcabcabc 循环移位 bcabcabca 继续 cabcabcab 继续 abcabcabc三次就得到一个一样的了,那么也就是说这个串中的任何循环移位串只要三次就会出现一样的,本来总个数是len,每三个一样是不是就是每个串出现len/3,这个三是不是就是我们KMP里面说的那个最小循环节。len/最小循环节 不就是最小循环节的周期数吗? so..直接KMP搞定次数,任何串出现的次数都是一样的,最后再返回来说下最小表示法。

最小表示法可以直接求出来自小的(或者是最大的)循环移位串的首字母是的下标,

比如dabc的小标就是2(从1开始)

核心代码很短

int GetMinId(char *str)

{

    int i = 0 ,j = 1 ,k = 0;

    while(i < len && j < len && k < len)

    { 

        int t = str[(i+k)%len] - str[(j+k)%len];

        if(!t) ++k;

        else 

        {

            t > 0 ? i = i + k + 1 : j = j + k + 1;

            if(i == j) j ++;

            k = 0;

        } 

    }

    return i < j ? i : j;

}

可以这么理解,先定义两个变量i,j表示的都是前缀的下标,每次更新的时候我们把不满足的下标往后更新,就是往后+,最后得到前面的那个小的就是答案,关键是为什么?

我是这样想的

首先核心就是

if(t > 0) i = i + k + 1;

else j = j + k + 1;

这个地方是什么情况,比如i代表的串是 abcd  j代表的串是abca此时的k肯定是3那么t>0这个时候i直接跳到d的后面,也就是i = i + k + 1,就是默认之间的都肯定不是答案,这个是关键,为什么之间的bcd都肯定不是答案的起点呢,原因是abcd 和abca比较的时候到k=3的时候发现不相等了,那么之前的一定是相等的,那么也就是说i的串的a和d之间的bcd当串首字母的时候肯定会被j的串abca中的bc当首字母比下去,因为bcd<bca cd< ca d < a就是没有必要再比较了,这个一开始可能很不容易理解,但是仔细想想会明白的,我说的是我自己的理解,也有可能有错误,还有就是提示一点,如果实在理解不了这个方法可以先写一个暴力的,然后在想,我就是这么干的,顺便给一个暴力的代码吧,暴力的很多时候也可以过题目,只不过要看数据。

int GetMinId(char * str)

{

   int len = stelen(str);

   int i = 0 ,j = 1 , k = 0;

   while(i < len && j < len && k < len)

   {

       int t = str[(i+k)%len] - str[(j+k)%len];

       if(!t) ++k;

       else 

       {

          if(t > 0) i = j;

          j ++;

          k = 0;

        }

   }

   return i;

}

下面是hdu3374代码

#include<stdio.h>

#include<string.h>

#define N 1000000 + 10

char str[N];

int next[N];

void GetNext(int m ,char *str)

{

    int j = 0 ,k = -1;

    next[0] = -1;

    while(j < m)

    {

        if(k == -1 || str[j] == str[k])

        next[++j] = ++k;

        else k = next[k];

    }

}

int GetMinId(int len ,char *str)

{

    int i = 0 ,j = 1 ,k = 0;

    while(i < len && j < len && k < len)

    {

        int t = str[(i+k)%len] - str[(j+k)%len];

        if(!t) ++k;

        else

        {

            t > 0 ? i = i + k + 1 : j = j + k + 1;

            if(i == j) j ++;

            k = 0;

        }

    }

    return i < j ? i : j;

}

int GetMaxId(int len ,char *str)

{

    int i = 0 ,j = 1 ,k = 0;

    while(i < len && j < len && k < len)

    {

        int t = str[(i+k)%len] - str[(j+k)%len];

        if(!t) ++k;

        else

        {

            t < 0 ? i = i + k + 1 : j = j + k + 1;

            if(i == j) j ++;

            k = 0;

        }

    }

    return i < j ? i : j;

}

int main ()

{

    int len;

    while(~scanf("%s" ,str))

    {

        len = strlen(str);

        GetNext(len ,str);

        int max = GetMaxId(len ,str) + 1;

        int min = GetMinId(len ,str) + 1;

        int c;

        if(next[len] && len % (len - next[len]) == 0)

        c = len / (len - next[len]);

        else c = 1;

        printf("%d %d %d %d\n" ,min ,c ,max ,c);

    }

    return 0;

}

hdu3374最小表示法+KMP的更多相关文章

  1. Hdu 5442 Favorite Donut (2015 ACM/ICPC Asia Regional Changchun Online 最大最小表示法 + KMP)

    题目链接: Hdu 5442 Favorite Donut 题目描述: 给出一个文本串,找出顺时针或者逆时针循环旋转后,字典序最大的那个字符串,字典序最大的字符串如果有多个,就输出下标最小的那个,如果 ...

  2. HDU-3374-String Problem(最小表示法, KMP)

    链接: https://vjudge.net/problem/HDU-3374 题意: Give you a string with length N, you can generate N stri ...

  3. hdu3374 最大最小表示法 +kmp

    #include <iostream> #include <algorithm> #include <string.h> #include <cstdio&g ...

  4. 【HDU3374】 String Problem (最小最大表示法+KMP)

    String Problem Description Give you a string with length N, you can generate N strings by left shift ...

  5. hdu3374 String Problem KMP+最大最小表示法

    Give you a string with length N, you can generate N strings by left shifts. For example let consider ...

  6. hdu3374 kmp+最小表示法

    Give you a string with length N, you can generate N strings by left shifts. For example let consider ...

  7. hdu-3374(kmp+最小表示法)

    题意:给你一个字符串,这个字符串我们可以把把他变成n个字符串按照以下规则:将当前字符串第一个放到字符串最后一位,字符串的下标依次向前推一位,比如:s[1] s[2 ]s[3] s[4]->s[2 ...

  8. HDU 3374 最小/大表示法+KMP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题意:给定一个串s,该串有strlen(s)个循环同构串,要求输出字典序最小的同构串的下标,字典 ...

  9. hdu5442(2015长春赛区网络赛1006)后缀数组+KMP /最小表示法?

    题意:给定一个由小写字母组成的长度为 n 的字符串,首尾相连,可以从任意一个字符开始,顺时针或逆时针取这个串(长度为 n),求一个字典序最大的字符串的开始字符位置和顺时针或逆时针.如果有多个字典序最大 ...

随机推荐

  1. MySQL使用入门--初识数据库

    MySQL使用入门 数据库概述 数据库是存放数据的仓库.在应用的开发中总是离不开数据的查询.处理.存储,例如图书管理系统就需要操纵和存储大量的数据.没有数据库之前我们使用文件存储数据,但是文件存储有很 ...

  2. spring事务:事务控制方式,使用AOP控制事务,七种事务传播行为,声明事务,模板对象,模板对象原理分析

    知识点梳理 课堂讲义 1)事务回顾 1.1)什么是事务-视频01 事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败. 1.2)事务的作用 事务特征(ACID) 原子 ...

  3. H5 简单实现打砖块游戏

    实现效果如图所示: 1.布局 在html中,声明  div1 作为作为带有边框的父物体,一切行为都要在 div1 中进行.创建小球ball.左右可滑动的板子bat,以及存放要销毁的砖块的父物体 bri ...

  4. List的主要实现类

    //ArrayList:List的主要实现类 /* * List中相对于Collection,新增加的方法 * void add(int index, Object ele):在指定的索引位置inde ...

  5. 数据搬运组件:基于Sqoop管理数据导入和导出

    本文源码:GitHub || GitEE 一.Sqoop概述 Sqoop是一款开源的大数据组件,主要用来在Hadoop(Hive.HBase等)与传统的数据库(mysql.postgresql.ora ...

  6. All I know about A/B Test (1) : 均值型指标与比值(率)型指标的计算区别

    因为最近在找实习,所以打算把自己之前学过的关数据分析的知识总结(复习)一下.在总结A/B test时,我发现中文互联网中关于A/B test的总结已经很多了,但是对于均值型指标和比值(率)型指标在设计 ...

  7. java例题_15 有小到大排序

    1 /*15 [程序 15 排序] 2 题目:输入三个整数 x,y,z,请把这三个数由小到大输出. 3 程序分析:我们想办法把最小的数放到 x 上,先将 x 与 y 进行比较,如果 x>y 则将 ...

  8. Windows上Docker Toolbox修改镜像源

    https://blog.csdn.net/weixin_36242811/article/details/90515835

  9. Spring(七篇)

    (一)Spring 概述 (二)Spring Bean入门介绍 (三)Spring Bean继续入门 (四)Spring Bean注入方试 (五)Spring AOP简述 (六)Spring AOP切 ...

  10. Install Tensorflow object detection API in Anaconda (Windows)

    This blog is to explain how to install Tensorflow object detection API in Anaconda in Windows 10 as ...