hdu3374-最小表示法&&kmp求循环节-String Problem

来源:互联网 发布:java中遍历数组 编辑:程序博客网 时间:2024/05/17 02:05

http://acm.hdu.edu.cn/showproblem.php?pid=3374
之前做过一道exkmp的题,就是先求的 循环节。就是用的这个代码的方法。。
开始先用表示法来算的,然后暴力枚举超时了,就想到用循环节式一下。
用string会超时,挂载也超时
给你一个串,分别输出
字典序最小同构串的 第一个字符位置(从1开始)
出现次数
字典序最大同构串的第一个位置
出现次数

#include <bits/stdc++.h>using namespace std;const int maxn=2e6+1000;int MAXR(char  s[]){    int len=strlen(s)/2;    int i=0;int j=1;int k=0;    while(i<len&&j<len){        k=0;        while(s[i+k]==s[j+k]&&k<len)k++;        if(k==len) return min(i,j);        if(s[i+k]<s[j+k]) i=max(i+k+1,j+1);        else if(s[i+k]>s[j+k]) j=max(j+k+1,i+1);    }    return min(i,j);}int MINR(char s[]){    //cout<<s<<"!!"<<endl;    int len=strlen(s)/2;   // cout<<len<<endl;    int i=0;int j=1;//int k=0;    while(i<len&&j<len){        int k=0;        while(s[i+k]==s[j+k]&&k<len)k++;        if(k==len) return min(i,j);        if(s[i+k]>s[j+k])            i=max(i+k+1,j+1);        else if(s[i+k]<s[j+k])         j=max(j+k+1,i+1);    }    return min(i,j);}int nex[maxn];int getnext(int len,char s[]){    nex[0]=-1;    int i=0;int k=-1;    while(i<len){          if(k==-1||s[i]==s[k]){             nex[++i]=++k;          }          else             k=nex[k];    }}int main(){   //ios::sync_with_stdio(false);    char  s[maxn];    while(~scanf("%s",s)){         int len=strlen(s);           getnext(len,s);           int siz=len-nex[len];//计算 循环节           int kk=0;           if(!(len%siz))               kk=len/siz;           else            kk=1;            for(int i=0;i<len;i++){                s[i+len]=s[i];            }           int max1=MAXR(s);           int min1=MINR(s);           int flag1=0;           int flag2=0;          printf("%d %d %d %d\n",min1+1,kk,max1+1,kk);    }    return 0;}
原创粉丝点击