循环字符串最大最小表示法模版

循环字符串最大最小表示法模版

定义字符串abcde和cdeab同构,因为abcde转两格即为cdeab,该字符串称为循环字符串。

循环字符串的字典序最小的同构字符串称为最小表示,最大表示同理。

这里只给模版,以后再深究。

int getMin(char *s) ///返回首位置
{
    int n=strlen(s);
    int i=0,j=1,k=0;
    while(i<n&&j<n&&k<n){
        int t=s[(i+k)%n]-s[(j+k)%n];
        if(!t) k++;
        else{
            if(t>0) i+=k+1;
            else j+=k+1;
            if(i==j) j++;
            k=0;
        }
    }
    return min(i,j);
}

int getMax(char *s)
{
    int n=strlen(s);
    int i=0,j=1,k=0;
    while(i<n&&j<n&&k<n){
        int t=s[(i+k)%n]-s[(j+k)%n];
        if(!t) k++;
        else{
            if(t<0) i+=k+1;
            else j+=k+1;
            if(i==j) j++;
            k=0;
        }
    }
    return min(i,j);
}

时间: 2024-11-10 00:11:02

循环字符串最大最小表示法模版的相关文章

【算法】字符串的最小表示法

字符串的最小表示法,就是对于一个字符串,可以将它的最后一位放到第一位来,依次类推,一共有n种变形,n为字符串长度 例如: s="00ab" 变形有(省略引号)b00a ab00 0ab0 一共4种 那么找到其中字典序最小的一个,用的算法便是这个. 定义三个指针,i,j,k 初始i=0;j=1;k=0 首先,如果s[i]<s[j]那么很明显j++ 如果s[i]>s[j]那么也很明显i=j++ 省下的就是如果s[i]==s[j]的时候. 这时候有一个性质就是在i和j之间的所有的

字符串的最小表示法

给定一个字符串,要求求出从某个下标开始,这个字符串的字典序最小,即字符串的最小表示法比如字符串bbbaaa,从下标3开始表示为aaabbb,字典序最小 暴力算法的时间复杂度为O(n^3)但是有线性的算法初始时,让i=0,j=1,k=0:分为三种情况,①如果str[i+k] == str[j+k] k++;②如果str[i+k] > str[j+k] i = i + k + 1, k = 0,  即最小表示不可能以str[i-->i+k]中的任一一个字符串开头③如果str[i+k] < s

HDU 4162 Shape Number(字符串,最小表示法)

HDU 4162 题意: 给一个数字串(length <= 300,000),数字由0~7构成,求出一阶差分码,然后输出与该差分码循环同构的最小字典序差分码. 思路: 第一步是将差分码求出:s[i] = (s[i] - s[i+1] + 8) % 8; 第二步是求出最小字典序的循环同构差分码,我之前没注意到字符串规模..直接用set做,MLE+TLE... 正确的方式应该是一种O(n)的解法,即最小表示法.//关于最小表示法的证明与详述请参考最小表示法:) 最小表示法算法: 初始时,i=0,j=

字符串最大最小表示法模板 ( 字典序最大最小 )

模板 int getMin(char *s) { int i = 0, j = 1, l; int len = strlen(s); while(i < len && j < len) { for(l = 0; l < len; l++) if(s[(i + l) % len] != s[(j + l) % len]) break; if(l >= len) break; if(s[(i + l) % len] > s[(j + l) % len]) { if

USACO 5.5.2 字符串的最小表示法

这道题是最小表示法的一个应用, 代码如下: /* ID: m1500293 LANG: C++ PROG: hidden */ #include <cstdio> #include <algorithm> #include <cstring> using namespace std; char s[100000 + 100]; int len; int mins(char s[], int len) { int i=0, j=1, k=0; while(i<len

字符串最小表示法模版

1 //O(n) 2 char s[N],ss[N*2]; 3 int n=strlen(s+1); 4 for(int i=1;i<=n;i++) 5 ss[i+n]=s[i]; 6 int i=1,j=2,k; 7 while(i<=n && j<=n){ 8 for(k=0;k<n && s[i+k] == s[j+k]; k++); 9 if(k==n) break; 10 if(s[i+k]>s[j+k]){ 11 i=i+k+1;

POJ 1509 循环同构的最小表示法

题目大意: 给定一个字符串,可以把一段尾部接到头部,这样找到一个最小的字符串 方案一: 利用循环同构中找最小表示的方法来解决 论文参考http://wenku.baidu.com/view/438cad13a2161479171128b6.html 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 #define N 10005 7 char

HDU 3374 exkmp+字符串最大最小表示法

题意 找到一个字符串中最先出现的最小(大)表示位置,和最小(大)表示串出现次数 分析 用最小(大)表示法求出最先出现的最小(大)表示位置,然后将串长扩两倍用exkmp找出现次数. Code #include<bits/stdc++.h> #define fi first #define se second #define lson l,mid,p<<1 #define rson mid+1,r,p<<1|1 #define pb push_back #define ll

字符串的最小最大表示法O(n)

以下介绍内容内容转自:http://blog.csdn.net/zy691357966/article/details/39854359 网上看了这篇文章后还是感觉有些地方讲的没有详细的证明所以添加了一点 红色字是博主写的 求字符串的循环最小表示: 上面说的两个字符串同构的,并没有直接先求出Min(s),而是通过指针移动,当某次匹配串长时,那个位置就是Min(s).而这里的问题就是:不是给定两个串,而是给出一个串,求它的Min(s),eg:Min("babba") = 4.那么由于这里