O - String Problem KMP 字符串最小表示法
2017-04-09 22:16
363 查看
Give you a string with length N, you can generate N strings by left shifts. For example let consider the string “SKYLONG”, we can generate seven strings:
String Rank
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
Input Each line contains one line the string S with length N (N <= 1000000) formed by lower case letters.OutputOutput four integers separated by one space, lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), the string’s times in the N generated strings, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.Sample Input
Sample Output
String Rank
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
Input Each line contains one line the string S with length N (N <= 1000000) formed by lower case letters.OutputOutput four integers separated by one space, lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), the string’s times in the N generated strings, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.Sample Input
abcder aaaaaa ababab
Sample Output
1 1 6 1 1 6 1 6 1 3 2 3 第一次的超时代码
#include<iostream> #include<set> #include<map> #include<vector> #include<string> #include<algorithm> using namespace std; /* 找一个字符串所有左移产生的字符串中(字符串长度个) 第一个字典序最小的序列所在位置 和出现次数(字符串长度除以最小循环节长度) 第一个字典序最大的序列所在位置 和出现次数 字典序最小或者最大 所在位置 就是向左移动次数 从前往后遍历 遇到比min小的字符就设置为起点,有相等的就循环比较后面的元素(这里时间复杂度n) 总的时间复杂度 n2 */ #define MAXN 1000001 char s[MAXN]; int Next[MAXN]; void kmp_pre(int l) { int j,k; j=0;k = Next[0] = -1; while(j<l) { if(k==-1||s[j]==s[k]) Next[++j] = ++k; else k = Next[k]; } } int main() { while(scanf("%s",s)!=EOF) { int len = strlen(s),Min=0,Max=0; kmp_pre(len); for(int i=1;i<len;i++) { if(s[i]<s[Min]) Min = i; else if(s[i]==s[Min]) { for(int j=1;j<len;j++) { if(s[(i+j)%len]<s[(Min+j)%len]) { Min = i; break; } } } if(s[i]>s[Max]) Max = i; else if(s[i]==s[Max]) { for(int j=1;j<len;j++) { if(s[(i+j)%len]>s[(Max+j)%len]) { Max = i; break; } } } } printf("%d %d %d %d\n",Min+1,len/(len-Next[len]),Max+1,len/(len-Next[len])); } }
#include<iostream> #include<set> #include<map> #include<vector> #include<string> #include<algorithm> using namespace std; /* 找一个字符串所有左移产生的字符串中(字符串长度个) 第一个字典序最小的序列所在位置 和出现次数(字符串长度除以最小循环节长度) 第一个字典序最大的序列所在位置 和出现次数 枚举方法求字典序最大或者最小字符串的算法n方太蠢了, 以最小为例:原因在于i失配的时候移动距离太小,没有充分利用 已知条件,比如i-i+k之间的数字显然是大于或者等于i的,所以这些部分没必要再枚举一遍了!直接让i=i+k */ #define MAXN 1000001 char s[MAXN]; int Next[MAXN]; void kmp_pre(int l) { int j,k; j=0;k = Next[0] = -1; while(j<l) { if(k==-1||s[j]==s[k]) Next[++j] = ++k; else k = Next[k]; } } int FindMin(char s[],int l) { int i=0,j=1,k=0; while(i<l&&j<l&&k<l) { if(s[(i+k)%l]==s[(j+k)%l]) k++; else if(s[(i+k)%l]>s[(j+k)%l]) { i = i+k+1; k = 0; } else { j = j+k+1; k = 0; } if(i==j) j++; } return min(i,j); } int FindMax(char s[],int l) { int i=0,j=1,k=0; while(i<l&&j<l&&k<l) { if(s[(i+k)%l]==s[(j+k)%l]) k++; else if(s[(i+k)%l]<s[(j+k)%l]) { i = i+k+1; k = 0; } else { j = j+k+1; k = 0; } if(i==j) j++; } return min(i,j); } int main() { while(scanf("%s",s)!=EOF) { int len = strlen(s); kmp_pre(len); int Max = FindMax(s,len),Min = FindMin(s,len); printf("%d %d %d %d\n",Min+1,len/(len-Next[len]),Max+1,len/(len-Next[len])); } }
相关文章推荐
- HDU3374(String Problem)字符串-最小表示法+KMP
- hdu 3374 String Problem kmp+字符串最小表示法+next数组性质
- hdu3374 String Problem KMP+最大最小表示法
- String Problem + 最大(最小)表示法+KMP
- String Problem HDU - 3374(字符串的最大最小表示)
- hdu String Problem(最小表示法入门题)
- String Problem HDU - 3374 (最大最小表示法)
- hdu 3374 String Problem(KMP+字符串最小最大表示)
- bzoj 2176: Strange string 字符串最小表示法
- 【string】KMP, 扩展KMP,trie,SA,ACAM,SAM,最小表示法
- HDU 3374 KMP +字符串最小表示
- String Problem --- hdu3374(kmp、字典序最大与最小)
- HDU 3374 String Problem(字符串最小表示+KMP )
- 【字符串最小(大)表示法+KMP求循环节】hdoj 3374 String Problem
- BZOJ 5130([Lydsy12月赛]字符串的周期-最小表示法+kmp)
- hdu 5442 F - Favorite Donut 后缀数组 / 字符串の最小表示法+kmp
- Minimum Expression of String 字符串最小表示
- BZOJ 2176: Strange string【字符串最小表示法
- [coj 1353 Guessing the Number]kmp,字符串最小表示法
- hdu 3374 String Problem(字符串最小最大表示法+kmp)