最小标示法模板 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<<1]={};
        cin>>(s+1);

        len=strlen(s+1);
        for(int i=1;i<=len;i++)
            s[len+i]=s[i];
        int j=2,i=1;
        while(i<=len && j<=len){
            int k=0;
            while(s[i+k]==s[j+k] && k<len)
                k++;
            if(s[i+k]>s[j+k])
                i=i+k+1;
            else
                j=j+k+1;
            if(i==j)j++;
        }
        cout<<min(i,j)<<‘\n‘;
    }
}

下面是进阶指南的模板

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[i+k]==s[j+k];k++);
    if(k==n)break;
    if(s[i+k]>s[j+k])
        i=i+k+1;
    else j=j+k+1;
    if(i==j)j++;
}
ans=min(i,j);

原文地址:https://www.cnblogs.com/zsben991126/p/10471669.html

时间: 2024-08-16 14:12:32

最小标示法模板 poj1509的相关文章

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

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

最小表示法(模板)

最小表示法就是对于一个循环字符串,其字典序最小的状态: 显然任意一个循环串的最小表示法是唯一的,那么可以同过比较两个循环串的最小表示法来判断它们是否相同: 对于朴素算法: 初始化: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++: 返回

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

#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)%l

【最小表示法】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

HDOJ3374 String Problem 【KMP】+【最小表示法】

String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1512    Accepted Submission(s): 668 Problem Description Give you a string with length N, you can generate N strings by left shifts

最大最小表示法

目的:已知一个串S,求S的循环的同构字符串S'中字典序最大/最小的一个,输出其位置,place∈[0,n-1] 设S=bcad,S'=bcad,cadb,adbc,dbca,最小表示的S'是adbc,位置是2,最大表示的S'是dbca,位置是3 时间复杂度:O(n) 自用模板: int get_minstring(char *s) //最小表示法 { int len=strlen(s); int i=0,j=1,k=0; while(i<len&&j<len&&

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=

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

【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game

给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开的位置在哪一横排,将这一排提到排序后的字符串数组最前面,求个"最大表示法",如果最大表示法的位置恰好在第一排的位置,那么可以用来更新答案. 如果不在第一排的位置,那么其所构成的仍然是合法的串,而且一定不会影响答案. 这是一个最小表示法的板子. #include<cstdio>