最小表示法和最大表示法模板

以下摘自http://blog.csdn.net/zy691357966/article/details/39854359

求字符串的循环最小表示:

上面说的两个字符串同构的,并没有直接先求出Min(s),而是通过指针移动,当某次匹配串长时,那个位置就是Min(s)。而这里的问题就是:不是给定两个串,而是给出一个串,求它的Min(s),eg:Min(“babba”) = 4。那么由于这里并非要求两个串的同构,而是直接求它的最小表示,由于源串和目标串相同,所以处理起来既容易又需要有一些变化:我们仍然设置两个指针,i, j,其中i指向0,j指向1,仍然采用上面的滑动方式:

(1) 利用两个指针i, j。初始化时i指向0, j指向1。

(2) k = 0开始,检验s[i+k] 与 s[j+k] 对应的字符是否相等,如果相等则k++,一直下去,直到找到第一个不同,(若k试了一个字符串的长度也没找到不同,则那个位置就是最小表示位置,算法终止并返回)。则该过程中,s[i+k] 与 s[j+k]的大小关系,有三种情况: 
证明的时候假设(i < j)的,无伤大雅 ;

(A). s[i+k] > s[j+k],则i滑动到i+k+1处 — 即s1[i->i+k]不会是该循环字符串的“最小表示”的前缀。

证明如下 

(B). s[i+k] < s[j+k],则j滑动到j+k+1处,原因同上。

(C). s[i+k] = s[j+k],则 k++; if (k == len) 返回结果。

注:这里滑动方式有个小细节,若滑动后i == j,将正在变化的那个指针再+1。直到p1、p2把整个字符串都检验完毕,返回两者中小于 len 的值。

(3) 如果 k == len, 则返回i与j中的最小值

如果 i >= len 则返回j 
如果 j >= len 则返回i

如果看了上一篇文章 很容易对这里的i,j 产生误会 误以为i为ans,j为比较指针

实际上这题中 i,j 都可能存有ans 两者互相更新,直到有一个更新后超过了len(包括len) 的时候 另一个即为正解

(4) 进一步的优化,例如:i要移到i+k+1时,如果i+k+1 <= p2的话,可以直接把i移到 j+1,因为,j到j+k已经检验过了该前缀比以i到i+k之间任何一个位前缀都小;j时的类似,移动到i+1。

这个优化就无需解释了

int getMin(int len) {
    int i = 0, j = 1;
    int l;
    while (i < len && j < len) {
        for (l = 0; l < len; l++)
            if (str[(i + l) % len] != str[(j + l) % len]) break;
        if (l >= len) break;
        if (str[(i + l) % len] > str[(j + l) % len]) {
            if (i + l + 1 > j) i = i + l + 1;
            else i = j + 1;
        }
        else if (j + l + 1 > i) j = j + l + 1;
        else j = i + 1;
    }
    return i < j ? i : j;
}

int getMax(int len) {
    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) {
                if (j + k + 1 > i) j = j + k + 1;
                else j = i + 1;
            }
            else if (i + k + 1 > j) i = i + k + 1;
            else i = j + 1;
            k = 0;
        }
    }
    return i < j ? i : j;

}
时间: 2024-08-11 03:36:15

最小表示法和最大表示法模板的相关文章

单链表的头插法和尾插法c语言实现

/*单链表的头插法和尾插法c语言实现*/ #include <stdio.h>#include <stdlib.h>#include <string.h>#define SIZE 100/*简单的定义一个链表节点的数据单元*/typedef struct student_t{ int num; char name[SIZE]; struct student_t* pNext;}studentList, *pStudentList; /*定义一个全局的静态的链表头节点指针

C实现头插法和尾插法来构建单链表(不带头结点)

链表的构建事实上也就是不断插入节点的过程.而节点的插入能够分为头插法和尾插法. 头插法就是在头结点后插入该节点,始终把该节点作为第一个节点.尾插法就是在链表的最后一个节点处插入元素,作为最后一个节点.假设想要了解链表的概念和其它链表操作.请參考<数据结构与算法之链表><C语言实现链表的基本操作>两篇文章.演示样例代码上传至  https://github.com/chenyufeng1991/HeadInsertAndTailInsert . // // main.c // Hea

采用头插插法和尾插法建立单项链表

PS: 来源2014年数据结构联考复习指导 Page27. #include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; const int END_INPUT = -1; typedef struct LNode { int data; struct LNode *next; }LNode, *LinkList; LinkList CreatList1(LinkList

C实现头插法和尾插法来构建链表

链表的构建其实也就是不断插入节点的过程.而节点的插入可以分为头插法和尾插法.头插法就是在头结点后插入该节点,始终把该节点作为第一个节点.尾插法就是在链表的最后一个节点处插入元素,作为最后一个节点.如果想要了解链表的概念和其他链表操作,请参考<数据结构与算法之链表><C语言实现链表的基本操作>两篇文章.示例代码上传至  https://github.com/chenyufeng1991/HeadInsertAndTailInsert . // // main.c // HeadIns

扩展欧几里得算法模板题 zoj 3609

Modular Inverse Time Limit: 2 Seconds      Memory Limit: 65536 KB The modular modular multiplicative inverse of an integer a modulo m is an integer x such that a-1≡x (mod m). This is equivalent to ax≡1 (mod m). Input There are multiple test cases. Th

C实现头插法和尾插法来构建非循环双链表(不带头结点)

在实际使用中,双链表比单链表方便很多,也更为灵活.对于不带头结点的非循环双链表的基本操作,我在<C语言实现双向非循环链表(不带头结点)的基本操作>这篇文章中有详细的实现.今天我们就要用两种不同的方式头插法和尾插法来建立双链表.代码上传至  https://github.com/chenyufeng1991/HeadInsertAndTailInsertDoubleList  . 核心代码如下: //尾插法创建不带头结点的非循环双向链表 Node *TailInsertCreateList(No

骆驼命名法,帕斯卡命名法和匈牙利命名法(转)

一.匈牙利命名法:广泛应用于象Microsoft Windows这样的环境中.      Windows 编程中用到的变量(还包括宏)的命名规则匈牙利命名法,这种命名技术是由一位能干的 Microsoft 程序员查尔斯?西蒙尼(Charles Simonyi) 提出的.        匈牙利命名法通过在变量名前面加上相应的小写字母的符号标识作为前缀,标识出变量的作用域,类型等.这些符号可以多个同时使用,顺序是先m_(成员变量), 再指针,再简单数据类型,再其他.例如:m_lpszStr, 表示指

席位分配问题——惯例Q值法和d&#39;hondt法的MATLAB程序

  本篇博文为追忆曾经写过的算法系列第四篇 温故知新 本篇于2009年发表于百度博客,当时还没接触CSDN,所以是文学和技术博客混淆,不过这个程序博文访问量突破2000,有不少网友评论互动,应该对很多人有一定的帮助. 程序介绍了数学建模中经典问题的两种解法,即席位分配问题! %适用于所有情况 BY Gu clear all clc %惯例Q值法分配席位,wy为席位数,ps为人数总和,R为分配方案 wy=19; P=[103 63 34] %菜单选项 MENUN=menu('选择方法','惯

hdu 4009 Transfer water(最小树形图:有向图的最小生成树模板)

题目: 链接:点击打开链接 题意: 有n个村庄,要求使得每个村庄都能得到水的最小费用.每个村庄可以通过挖井或从其他村庄修水路获得水.挖井的费用是房子的高度乘以X,修水道的费用和有向图边的起点和终点的高度有关. 思路: 代码: #include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std; #define inf 0x3f3f3f3f