字符串最小表示法

第一种

int get_minstring(char s[])
{
    int n =strlen(s);
    int i = 0, j = 1, k;
    while (i < n&&j < n)
    {
        for (k = 0; k < n&&s[(j + k) % n] == s[(i + k) % n]; k++);
        if (k == n)  break;
        if (s[(i + k)%n]>s[(j + k)%n])
        {
            i = i + k + 1;
            if (i == j) i++;
        }
        else
        {
            j = j + k + 1;
            if (i == j) j++;
        }
    }
    return min(i, j);
}

第二种

int get_minstring(char s[])
{
    int n = strlen(s + 1);
    for (int i = 1; i <= n; i++)
        s[n + i] = s[i];
    int i = 1, j = 2,k;
    while (i <= n&&j <= n)
    {
        for ( k = 0; k < n&&s[j + k] == s[i + k]; k++);
        if (k == n)  break;
        if (s[i + k]>s[j + k])
        {
            i = i + k + 1;
            if (i == j) i++;
        }
        else
        {
            j = j + k + 1;
            if (i == j) j++;
        }
    }
    return min(i, j);
}

原文地址:https://www.cnblogs.com/xiaoguapi/p/10367551.html

时间: 2024-10-12 09:28:42

字符串最小表示法的相关文章

[coj 1353 Guessing the Number]kmp,字符串最小表示法

题意:给一个字符串,求它的最小子串,使得原串是通过它重复得到的字符串的一个子串. 思路:先求最小长度,最小循环长度可以利用kmp的next数组快速得到,求出长度后然后利用字符串最小表示法求循环节的最小表示即可. #pragma comment(linker, "/STACK:10240000") #include <map> #include <set> #include <cmath> #include <ctime> #include

没有来源的题(似乎是什么POI?) 字符串——最小表示法

[题目描述]? 给你两个长度为 \(n\) 的字符串,问能否通过将某一字符串的一个前缀接到该串的后面使得两个字符串相等.若可以,你还可能被要求输出通过上述操作所能得到的字典序最小的字符串. [输入格式] ? ? 第一行两个整数 \(n,T\). ? 接下来两行,每行一个长度为 \(n\) 的字符串. [输出格式] ? 若可以,输出 \(TAK\),否则输出 \(NIE\).如果 \(T=1\),你还需要在下一行输出字典序最小的字符串. [数据范围] \(n \le 1000000\) 首先,什么

【转载】字符串最小表示法-O(n)算法

原博客链接:http://blog.csdn.net/zy691357966/article/details/39854359 未授权,侵权删. 因为这篇博客写得真好..转载了.. 红色的字是原博主写的,蓝色的字是我加的. ------------------------------------------------------------------------------------------------------------------------------------------

字符串最小表示法模版

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;

hdu 2609 字符串最小表示法 虽然不是很懂 还是先贴上来吧。/,。/

还需要再消化一下这个算法.. 今天没有时间了,, 六级过了 就有大把时间 快活啊!#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<set> using namespace std; int getmin(string s) { int n=s.size(); int i=0,j=1,k=0,t; while(i<n &&a

字符串最小表示法 O(N)

#include<iostream> #include<stdio.h> #include<cstring> #define rep(i,n) for(int i=0;i<n;i++) #define sf scanf #define pf printf using namespace std; int MinimumRepresentation(char *s, int l) { int i = 0, j = 1, k = 0, t; while(i <

Vijos 有根树的同构问题【字符串---最小表示法】

背景 经典题 描述 所谓图的同构是指两个图“相同”.图的同构有着广泛的应用,比如当要对一批图施行某种操作的时候,如果能发现其中有一些图是同构的,就可以在这些同构的图中只保留一个,从而降低工作量.例如,图1所示的T1和T3就是同构的. 图的同构的定义:给出两个图G1=(V1,E1),G2=(V2,E2).如果存在一个V1到V2的一一映射f,使得(x,y)是G1的边,当且仅当(f(x),f(y))是G2的边,则称G1和G2是同构的.也就是说,我们只关心顶点间的拓扑关系而不关心顶点的编号. 任意图的同

2018/2/24 每日一学 字符串最小表示法

非常简单,直接上代码: int minimalRepresentation() { int n = strlen(str); int i = 0,j = 1, k = 0; while(i<n && j<n && k<n) { int t = str[(i+k)%n] - str[(j+k)%n] ; if(t == 0) k++; else { if(t>0) i+=k+1; else j+=k+1; if(i==j) j++; k = 0; }

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=