hdu 3374 String Problem (最小表示法+kmp next[])
来源:互联网 发布:c语言中乘方怎么表示 编辑:程序博客网 时间:2024/05/16 15:07
小记:这题蛮好,比较有意思
思路:字母序最小和最大的串,我们可以用最小表示法和最大表示法解决,比较简单。参考
然后就是出现的次数,这个解决方案可以直接利用kmp的next数组直接暴力求取最大和最小的出现的次数。
但是这里面却还是有特性的。我们来看:
我们的next数组的含义就是: next[j] 表示 字符串S,S[0,j-1]的前缀和后缀的相等的最长长度。这一点要好好理解下。毕竟也是kmp的精髓
然后我们来看next[len]的意义,len是S的长度。next[len]就意味着,S的前缀和后缀的相等部分的最长长度。
然后再看len - next[len], 这个值是非常有意义的,假设为sublen。 它代表着去除那个最长前缀所剩下的字符的个数(或者后缀,但值都是一样的),
而这个值就是关键所在,如果它能被len整除,就意味着,整个S有len/sublen个相同的sublen,注意是相同是从sublen的始到终每一块对应的字符都是一样的。
这--------------- --- 假设是分开的18个字符,但是代表字符串S,空格不算,为了区分,做个例子
前面15个代表next[len]值, sublen就等于3, 而根据next数组的意义,显然
--- --------------- 这个后缀是和前面那个前缀相同的, 那么最后那一部分肯定是相同的,因此
最后3个字符,和倒数6-4,这个3个字符也是相同的,同理可以一直往前延续,所以结果就出来了
当len/sublen可以整除时,结果是无论从那一个字符开始,它循环表示的串 都会出现len/sublen次。
而不能整除时,因为有某些字符挡在哪里,你循环表示时,就会打乱你的次序,因此无论从那一个字符开始,它循环表示的串出现的次数都是1次。
答案显而易见。这样是不是简化了很多。
代码:
#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <map>#include <set>#include <vector>#include <stack>#include <queue>#include <algorithm>using namespace std;#define mst(a,b) memset(a,b,sizeof(a))#define REP(a,b,c) for(int a = b; a < c; ++a)#define eps 10e-8const int MAX_ = 1000010;const int N = 500000;const int INF = 0x7fffffff;char str[MAX_], str1[MAX_];int hash[MAX_];int next[MAX_];int a[MAX_];map<string, int> mp;void compute_next(char substr[]) { int i,j, len; len = strlen(substr); i=0; next[0]=-1; j=-1; while(i < len) { if(j == -1 || substr[i] == substr[j]) { i++; j++; //修正的地方就发生下面这4行 if(substr[i] != substr[j] ) next[i] = j; else next[i] = next[j]; } else { j = next[j]; } }}int Minimize(char str[]) { int i= 0, j= 1, len, k =0; len = strlen(str); while(i < len && j < len && k < len) { int t = str[(i+k)%len] - str[(j+k)%len]; if(!t)++k; else { if(t > 0)i = i+k+1; else j = j+ k + 1; if(i == j)++j; k = 0; } } return i>j?j:i;}int Maximize(char str[]) { int i= 0, j= 1, len, k =0; len = strlen(str); while(i < len && j < len && k < len) { int t = str[(i+k)%len] - str[(j+k)%len]; if(!t)++k; else { if(t < 0)i = i+k+1; else j = j+ k + 1; if(i == j)++j; k = 0; } } return i>j?j:i;}int main() { int T, n, m, numa = 0, numb = 0,ans; bool flag = 0; string s = ""; while(~scanf("%s", str)) { numa = Minimize(str); numb = Maximize(str); compute_next(str); int len = strlen(str); m = len - next[len]; ans = len%m?1:len/m; printf("%d %d %d %d\n",numa+1,ans,numb+1, ans); } return 0;}
- hdu 3374 String Problem (最小表示法+kmp next[])
- HDU 3374 String Problem(最大最小表示法模板+KMP+next数组的运用)
- hdu 3374 String Problem kmp+字符串最小表示法+next数组性质
- HDU 3374String Problem(最大最小表示法+KMP)
- hdu 3374 String Problem (最小表示法+KMP)
- hdu 3374 String Problem 【kmp+最小(大)表示法】
- hdu 3374 String Problem(最小表示法+kmp)
- HDU 3374 String Problem(最小表示法·KMP)
- hdu 3374 String Problem (kmp+最大最小表示法)
- HDU 3374 String Problem (KMP+最大最小表示法)
- HDU 3374 String Problem(最大最小表示法+kmp)
- hdu 3374 String Problem(KMP+最大最小表示法)
- HDU 3374 String Problem(最小最大表示法+KMP)
- HDU 3374 String Problem KMP-最小最大表示法
- hdu 3374 String Problem(字符串最小最大表示法+kmp)
- 【KMP】 HDU 3374 String Problem 最小表示法
- HDU 3374 String Problem (KMP+最大最小表示)
- HDU 3374 String Problem (KMP+最大最小表示)
- Easyui扩展验证
- 谈谈对Spring的理解
- JSP 隐藏域 单选按钮 复选按钮
- HDU 2014 青年歌手大奖赛_评委会打分
- ImageButton
- hdu 3374 String Problem (最小表示法+kmp next[])
- 利用securecrt在linux与windows之间传输文件
- 处理大数据的排序(源自书籍:编程珠玑第二版)
- 【 Visual C++】游戏开发笔记之二——最简单的DirectX,vc窗口的编写
- 程序员必看的文章
- Linux Shell编程入门
- usaco3.2.5饲料调配
- 认证
- SQL Server表分区