题意:
      给你一个最长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 - 3374 String Problem(最小表示法+最大表示法+KMP的next数组)

    题目链接:点击查看 题目大意:给出一个字符串,现在问字符串不断向左循环所能形成的n个字符串中,字典序最小和最大的字符串的编号为多少,分别有多少个 题目分析:字符串最小表示法的模板题,证明和模板都是看大 ...

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

    题意:给你一个字符串,并让他不断的进行循环左移,问字典序最小的字符串是第几个,出现的次数是多少,最大的字符串是第几个,出现的次数是多少? 分析:最小字符串和最大字符串用最小表示法即可找到,出现的次数, ...

  3. 【题】【二维KMP】NKOJ3807 卜拉美古塔与最小表示法

    NKOJ3807 卜拉美古塔与最小表示法 时间限制 : - MS 空间限制 : 165536 KB 评测说明 : 1000ms 问题描述 /* 婆罗摩笈多先生在中国也十分著名,并且更加著名的是一个以他 ...

  4. 字符串处理 —— 最大最小表示法

    [概述] 最大最小表示法用于解决字符串的同构问题,其在复杂度为 O(n) 的时间内求出一个字符串的所有同构串中字典序最大(小)的串的起始位置. 应用: 给出 n 个循环字符串判断有多少不同字符串:逐个 ...

  5. HDU - 3374(最小表示法+最大表示法)

    hdu3374 题意: 给你一个字符串,问这个字符串经过移动后的字典序最小的字符串的首字符位置和字典序最大的字符串的首字符的位置,和能出现多少次最小字典序的字符串和最大字典序的字符串 题解: 利用最小 ...

  6. 字符串循环同构的最小表示法(转)

    循环字符串的最小表示法的问题可以这样描述: 对于一个字符串S,求S的循环的同构字符串S'中字典序最小的一个. 由于语言能力有限,还是用实际例子来解释比较容易: 设S=bcad,且S'是S的循环同构的串 ...

  7. SZUACM集训字符串基础总结: 字符串最小表示 ,KMP, EXKMP, Manracher, Trie树,字符串的hash; 附带一写常见的运用技巧,邝斌大佬的板子和例题[持续更新]

    第一部分 字符串的匹配<-------->KMP 模式匹配:子串的定位运算称为串的模式匹配或串匹配. 假设有两个串S,T,设S为主串,也称正文串,T为子串,也称为模式,在主串S中查找与模式 ...

  8. 几个冷门字符串算法的学习笔记(最小表示法,exKMP,Lyndon Word)

    所有下标均从1开始 最小表示法 给定一个串,求字典序最小的循环同构. 我们把串复制一遍接在后面,然后求出[1,N][1,N][1,N]开始的长为NNN的子串中最小的 先设i=1,j=2i=1,j=2i ...

  9. bzoj 1398: 寻找主人 AC自动机+最小表示法

    题目大意: 给定两个序列判断是否循环同构,若循环同构则输出最小表示 题解: 因为没有样例输入输出,一开始没看到要求输出最小表示 Wa一大页. 但不得不说bzoj还是挺高效的: 赞一个 XD.jpg 判 ...

最新文章

  1. Nature发文:深度学习系统为什么这么好骗?
  2. 常见汉字Unicode编码
  3. VTK:Utilities之ArrayCalculator
  4. c语言斐波那契数列_视频丨神奇的斐波那契数列科学性与艺术性
  5. java properties 路径问题_Java 读取Properties文件时应注意的路径问题
  6. 支持mysql的报表开发工具_你不知道的mysql的3W法,内附超好用的报表工具
  7. 行云管家堡垒机的使用方法之二——新增登录凭证
  8. 整数区间(信息学奥赛一本通-T1324)
  9. Android 文件md5校验
  10. 免疫算法(matlab)
  11. 给敏捷软件开发的26条建议
  12. Power BI+Power Apps联动初尝试
  13. python Beautiful Soup常用过滤方法
  14. R语言 【integrate】函数
  15. [Database] 关系型数据库中的MVCC是什么?怎么理解?原理是什么?MySQL是如何实现的?
  16. 【生活】如何线上办理持有广州社保人员的异地分娩医保登记 - 定点医院 - 异地就医报销相关
  17. Android、APP、APK 、华为报感染病毒 a.gray.Bulimia.a 已解决 (精)
  18. html加拼音注释,HTML——格式化文本标记、拼音/音标注释ruby 标记和rt/rp 标记、段落缩进标记blockquote、预格式化标记pre...
  19. HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理。...
  20. iOS 使用AFNetworking-----cpf

热门文章

  1. [转] 用Firebug调试JavaScript
  2. legend3---lavarel安装debugbar工具条
  3. 洛谷P1541 乌龟棋
  4. SQL必知必会——插入数据(十五)
  5. Python爬虫之BeautifulSoup和requests的使用
  6. 团队-石头,剪刀,布-设计文档
  7. JZOJ 3.25 1419——【汕头市选2012初中组】排序(sort)
  8. linux usb驱动框架
  9. Ubuntu 虚拟机空间不足增加空间笔记
  10. 关于Oracle中in,exists 与 not in, not exists