HDU3374 String Problem(KMP + 最小表示法)
题目链接:HDU3374
题目大意:给你一个字符串,项链一样的可以循环表示 例如“SKYLONG”可以有7中表示形式。
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
求出字典序最小和字典序最大的串以及他们的出现次数。
思路:
KMP求出循环节,最小表示法求出最小位置,最大位置
最小表示法模板题
【代码】
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 1000000 + 10; char s[maxn]; int nextv[maxn]; int len; void getNext(){ //KMP的next数组 int i = 0 , j = -1; nextv[0] = -1; while(i < len){ if(j == -1 || s[i] == s[j]) nextv[++i] = ++j; else j = nextv[j]; } } int minRepresentation(bool flag){ int i = 0,j = 1,k = 0; while(i <len && j < len && k < len){ int tmp = s[(i + k)%len] - s[(j + k) % len]; if(tmp == 0) k++; else{ if(flag? (tmp > 0):(tmp<0)) //如果 flag求出字典序最小,否则 求出最大 i += k+1; else j += k + 1; if(i == j) j ++ ; k = 0; } } return min(i,j); } int main(){ while(scanf("%s",s)!=EOF){ int minlen; // memset(nextv,0,sizeof(nextv)); len = strlen(s); getNext(); int length = len - nextv[len]; int num; if (len % length == 0) num = len /length; //如果出现循环节 else num = 1; printf("%d %d %d %d\n",minRepresentation(1)+1,num,minRepresentation(0)+1,num); } return 0; }