字符串的最大最小表示法 模板

#include<iostream>
#include<string>
using namespace std;
/*
用最小表示法求字符串S的最小字典序
返回字典序最小的串的首字母位置
*/
int minstr(char s[])
{
    int len=strlen(s);
    int i=0,j=1;
    while(i<=len-1 && j<=len-1)
    {
        int k=0;
        while(k<=len-1 && s[(i+k)%len]==s[(j+k)%len])
            k++;
        if(k>=len)
            break;
        if(s[(i+k)%len]>s[(j+k)%len])
            i=max(i+k+1,j+1);////此时s[i+1]到s[i+k]都不可能是最小字符串的开头,而且s[i+1]到s[j]也不可能是最小字符串的开头(s[i]开头的字符串与s[j]开头的字符串在比较,本身已经说明s[i]开头的字符串小于以s[i+1]开头到以s[j-1]开头的字符串了)
        else
            j=max(j+k+1,i+1);//同上道理
    }
    return min(i,j);
}
/*
用最大表示法求字符串S的最大字典序
返回字典序最大的串的首字母位置
*/
int maxstr(char s[])
{
    int len=strlen(s);
    int i=0,j=1;
    while(i<=len-1 && j<=len-1)
    {
        int k=0;
        while(k<=len-1 && s[(i+k)%len]==s[(j+k)%len])
                k++;
        if(k>=len)
            break;
        if(s[(i+k)%len]<s[(j+k)%len])
            i=max(i+k+1,j+1);
        else
            j=max(j+k+1,i+1);
    }
    return min(i,j);
}
int main()
{

return 0;
}
时间: 2024-11-10 10:27:05

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

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

模板 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

最小标示法模板 poj1509

最小标示法:给定一个字符串,不断将其最后一个字符放到开头,最终会得到n个字符串,称这n个字符串循环同构,这些字符串中字典序最小的一个,就是最小表示法 #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define maxn 1000005 int len; int main(){ int t; cin>>t; while(t--){ char s[maxn&

最小表示法(模板)

最小表示法就是对于一个循环字符串,其字典序最小的状态: 显然任意一个循环串的最小表示法是唯一的,那么可以同过比较两个循环串的最小表示法来判断它们是否相同: 对于朴素算法: 初始化:i = 0, j = 1, k = 0; 若 s[i] < s[j],j++: 若 s[i] > s[j],i = j, j++: 若 s[i] == s[j],则 k++,直至 s[i + k] != s[j + k] 对于 s[i + k] < s[j + k],j++: 否则 i = j, j++: 返回

【最小表示法】BZOJ1398-寻找朋友

[题目大意] 判断两个字符串是否循环同构. [思路] 我一开始的做法是直接同时在两个字符串上求最小表示法,只有部分测试点能过,理由未知,以后再来思考. 现在做法:分别求出两个字符串的最小表示法,再比较是否相等. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int MAXN=100

【最小表示法】BZOJ2882-工艺

[题目大意] 求一个循环数列的最小表示法. [思路] 最小表示法模板题.之前用SAM做的,MLE了hhhhh戳☆ 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int MAXN=300000+50; 7 int s[MAXN*2],n; 8 9 void init() 10 { 1

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=

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

循环字符串最大最小表示法模版 定义字符串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(

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

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

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

字符串的最小表示法,就是对于一个字符串,可以将它的最后一位放到第一位来,依次类推,一共有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之间的所有的