HDU 3374

HDU 3374

题意:求出字典序最小串,最子串的位置和个数(字符串是头尾相连的)
思路:个数的话只看循环节个数就行了,但是最小串,最大串,怎么找出位置呢?O(n),主角登场:最小表示法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e6+5;
int len,nxt[maxn],cnt;
char a[maxn];
void kmp_pre1()
{
    
    
    int i=0,j=nxt[0]=-1;
    while(i<len)
    {
    
    
        while(j!=-1&&a[i]!=a[j])
            j=nxt[j];
        nxt[++i]=++j;
    }
}
int getmin(char *s)
{
    
    
    int n=cnt;
    int i=0,j=1,k=0,t;
    while(i<n && j<n && k<n)
    {
    
    
        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 i<j?i:j;
}
int getmax(char *s)
{
    
    
    int n=cnt;
    int i=0,j=1,k=0,t;
    while(i<n && j<n && k<n)
    {
    
    
        t=s[(i+k)%n]-s[(j+k)%n];
        if (!t) k++;
        else
        {
    
    
            if (t>0) j+=k+1;
            else i+=k+1;
            if (i==j) j++;
            k=0;
        }
    }
    return i<j?i:j;
}
int main()
{
    
    
    while(~scanf("%s",a))
    {
    
    
        len=strlen(a);
        int st=1,ed=len,n=len;
        kmp_pre1();
        if(n%(n-nxt[n])==0)
            cnt=(n-nxt[n]);
        else
            cnt=len;
        int pos1=1,pos2=1;
        pos1+=getmin(a);
        pos2+=getmax(a);
        if(n%(n-nxt[n])==0)
            printf("%d %d %d %d\n",pos1,n/(n-nxt[n]),pos2,n/(n-nxt[n]));
        else
            printf("%d %d %d %d\n",pos1,st,pos2,st);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43653111/article/details/102595574