最大最小表示法

目的:已知一个串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&&k<len)
    {
        int t=s[(i+k)%len]-s[(j+k)%len];
        if(t==0)
            k++;
        else
        {
            if(t>0)
                i=i+k+1;
            else
                j=j+k+1;
            if(i==j)
                j++;
            k=0;
        }
    }
    return min(i,j);
}
 
int get_maxstring(char *s)   //最大表示法
{
    int len=strlen(s);
    int i=0,j=1,k=0;
    while(i<len&&j<len&&k<len)
    {
        int t=s[(i+k)%len]-s[(j+k)%len];
        if(t==0)
            k++;
        else
        {
            if(t>0)
                j=j+k+1;
            else
                i=i+k+1;
            if(i==j)
                j++;
            k=0;
        }
    }
    return min(i,j);
}
View Code

hdu3374,求最大最小表示法的位置+出现的次数,出现次数=循环节,kmp即可

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int get_minstring(char *s)
{
    int len=strlen(s);
    int i=0,j=1,k=0;
    while(i<len&&j<len&&k<len)
    {
        int t=s[(i+k)%len]-s[(j+k)%len];
        if(t==0)k++;
        else 
        {
            if(t>0)i+=k+1;
            else j+=k+1;
            if(i==j)j++;
            k=0;
        }
    }
    return min(i,j);
}
int get_maxstring(char *s)
{
    int len=strlen(s);
    int i=0,j=1,k=0;
    while(i<len&&j<len&&k<len)
    {
        int t=s[(i+k)%len]-s[(j+k)%len];
        if(t==0)k++;
        else
        {
            if(t>0)j+=k+1;
            else i+=k+1;
            if(i==j)j++;
            k=0; 
        }
    }
    return min(i,j);
}
int Next[maxn];
void get_next(char *p)
{
    int m=strlen(p);
    Next[0]=Next[1]=0;
    for(int i=1;i<m;i++)
    {
        int j=Next[i];
        while(j&&p[i]!=p[j])j=Next[j];
        Next[i+1]=p[i]==p[j]?j+1:0;
    }
}

int main()
{
    char s[maxn];
    while(scanf("%s",s)!=EOF)
    {
        int l=get_minstring(s);
        int r=get_maxstring(s);
        get_next(s);
        int len=strlen(s);
        int cal=len-Next[len],times=len/cal;
        printf("%d %d %d %d
",l+1,times,r+1,times);
    } 
    return 0;
} 
View Code

hdu2609,n个01串(长度不超100),如果两串是同构字符串则为同一种,求有几种串

#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
int get_minstring(string s)
{
    int len=s.size();
    int i=0,j=1,k=0;
    while(i<len&&j<len&&k<len)
    {
        int t=s[(i+k)%len]-s[(j+k)%len];
        if(t==0)k++;
        else
        {
            if(t>0)i+=k+1;
            else j+=k+1;
            if(i==j)j++;
            k=0;
        }
    }
    return min(i,j);
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        map<string,int>mp;
        int ans=0;
        for(int i=0;i<n;i++)
        {
            string s1;
            cin>>s1;
            int l=get_minstring(s1),len=s1.size();
            string s2=s1.substr(l,len-l)+s1.substr(0,l);
            if(mp[s2]==0)ans++;
            mp[s2]++;
        }
        printf("%d
",ans);
    }
    return 0;
}
View Code

...

原文地址:https://www.cnblogs.com/myrtle/p/11517078.html