HDU 3374 最小/大表示法+KMP
Posted キリト
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3374 最小/大表示法+KMP相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374
题意:给定一个串s,该串有strlen(s)个循环同构串,要求输出字典序最小的同构串的下标,字典序最小的出现次数,最大的同构串的下标,字典中最大的出现次数。
思路:对于求循环同构的字典序最小可以用最小表示法求得,最大也是一样。然后设ds为字符串s+s。然后就可以用KMP求最小串在ds出现的次数和最大串出现的次数了。
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<set> using namespace std; const int MAXN = 1000000 + 5; typedef long long int LL; #define INF 0x3f3f3f3f int Representation(char *s,int l,bool flag){ //flag:0 最小表示法 flag:1 最大表示法 int i = 0, j = 1, k = 0; while (i < l&&j < l&&k < l){ int li, lj; li = (i + k) >= l ? i + k - l : i + k; lj = (j + k) >= l ? j + k - l : j + k; if (s[li] == s[lj]){ k++; } else{ if (!flag){ if (s[li]>s[lj]){ i = i + k + 1; } else{ j = j + k + 1; } } else{ if (s[li]<s[lj]){ i = i + k + 1; } else{ j = j + k + 1; } } if (i == j){ j++; } k = 0; } } return i < j ? i : j; } int Next[MAXN]; void getnext(char *s,int lens){ //KMP的next数组 int j, k; j = 0; k = -1; Next[0] = -1; while (j < lens){ if (k == -1 || s[j] == s[k]){ Next[++j] = ++k; } else{ k = Next[k]; } } } int KMP_Count(char *s,int lens,char *t,int lent){ //计算t串在s串中出现的次数 int ans = 0, j = 0; memset(Next, 0, sizeof(Next)); getnext(t,lent); for (int i = 0; i < lens; i++){ while (j>0 && s[i] != t[j]){ j = Next[j]; } if (s[i] == t[j]){ j++; } if (j == lent){ ans++; j = Next[j]; } } return ans; } char str[MAXN], dstr[MAXN*2],minstr[MAXN],maxstr[MAXN]; //原串,原串*2后的串,字典序最小的串,字典序最大的串 int main() { while (~scanf("%s", str)){ int len = strlen(str); for (int i = 0; i < len * 2 ; i++){ dstr[i] = str[(i%len)]; } //计算最小 int minstart = Representation(str, len,0); for (int i = 0; i < len; i++){ minstr[i] = str[(i + minstart) % len]; } int mincount = KMP_Count(dstr, len * 2 - 1, minstr, len); //计算最大 int maxstart = Representation(str, len,1); for (int i = 0; i < len; i++){ maxstr[i] = str[(i + maxstart) % len]; } int maxcount = KMP_Count(dstr, len * 2 - 1, maxstr, len); printf("%d %d %d %d\n", minstart + 1,mincount , maxstart + 1, maxcount); } return 0; }
以上是关于HDU 3374 最小/大表示法+KMP的主要内容,如果未能解决你的问题,请参考以下文章
HDOJ3374 String Problem KMP+最小表示法