HDU 3374 KMP-最小最大表示法的原理详解
来源:互联网 发布:学生基本护肤步骤知乎 编辑:程序博客网 时间:2024/06/07 10:26
题目链接:传送门
String Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3157 Accepted Submission(s): 1275
Problem Description
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.
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.
Output
Output 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
abcderaaaaaaababab
Sample Output
1 1 6 11 6 1 61 3 2 3
思路:刚学会这个代码,重点是代码有一个地方不好搞明白(一会儿重点解释代码的原理,自己想的原理,我也不知道对不对)。
出现的次数应该都能想到,求出字符串的最小周期x是多少。
int p=1; if(ls%(ls-nex[ls])==0)//ls-nex[ls]为循环节。ls为串长度 p=ls/(ls-nex[ls]);p即为次数。
怎么求最大(小)的子串排第几呢。模拟代码自己先理解,代码不算难理解。(后面我只会解释当时困惑我的地方)
int getminmax(int flag) //求最小值时flag=0,最大值为1;{ int i=0,j=1,k=0; while(i<ls&&j<ls&&k<ls) { int t=s[(i+k)%ls]-s[(j+k)%ls]; if(!t) k++; else { if(flag) { if(t>0) j+=k+1; else i+=k+1; } else { if(t>0) i+=k+1; else j+=k+1; } if(i==j) j++; k=0; } } return i>j?j:i;}
当时一直搞不懂为什么j+=k+1,i+=k+1。为什么i和j可以这样跳呢,请思考一下(它的原理):
若我现在要找最小串,两个比较的串的开头分别是i,j,串比较的长度是k+1( t ! =0 ),如果 t > 0 ( 串 i > 串 j ) 请思考在这两个串( i 和 j )的前(k+1)位,你是否能在串i的前(k+1)位中找到一个子串,使得这个子串比串 j 的前几位还小,答案是肯定找不到的。(假设你找到了一个,也就是说存在一个串 i 的前k+1位的子串比 j 的前几位还小,那么你再退回去重新从i,j 的第一位开始比较,一定得到的是 t < 0 ( 这就与前边的t>0矛盾了))所以假设不成立,所以你在串i的前(k+1)位中找不到一个比 j 小的子串 ,那么你就能可以不用考虑串i的前k+1位了,所以直接跳到k+1位的下一位。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=1000005;char s[N];int ls,nex[N];void getnext(){ nex[0]=-1; int x=-1,y=0; while(y<ls) { while(x!=-1&&s[x]!=s[y]) x=nex[x]; nex[++y]=++x; } return ;}int getminmax(int flag) //最小最大表示法0、1{ int i=0,j=1,k=0; while(i<ls&&j<ls&&k<ls) { int t=s[(i+k)%ls]-s[(j+k)%ls]; if(!t) k++; else { if(flag) { if(t>0) j+=k+1; else i+=k+1; } else { if(t>0) i+=k+1; else j+=k+1; } if(i==j) j++; k=0; } } return i>j?j:i;}int main(){ while(~scanf("%s",s)) { ls=strlen(s); getnext(); int p=1; if(ls%(ls-nex[ls])==0) p=ls/(ls-nex[ls]); printf("%d %d %d %d\n",getminmax(0)+1,p,getminmax(1)+1,p); } return 0;}
阅读全文
0 0
- HDU 3374 KMP-最小最大表示法的原理详解
- HDU 3374 KMP 最大表示法 最小表示法
- HDU 3374 String Problem(最小最大表示法+KMP)
- HDU 3374 String Problem KMP-最小最大表示法
- 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+next数组的运用)
- HDU 3374 String Problem (KMP+最大最小表示)
- hdu 3374 String Problem(KMP+字符串最小最大表示)
- HDU 3374 String Problem (KMP+最大最小表示)
- HDU 3374 String Problem (KMP+最大最小表示)
- HDU 5442 Favorite Donut 最大最小表示法+KMP
- hdu 3374 最小表示法加 KMP
- HDU(3374) (KMP + 最小表示法)
- QT相关资源
- libevent库介绍--事件和数据缓冲
- Handler 线程中的使用
- 树:树、森林、二叉树的转换
- scala集合浅谈
- HDU 3374 KMP-最小最大表示法的原理详解
- Mac之Security工具使用总结
- iOS 使用UITextField自动格式化银行卡号
- list集合增加时去重
- Python中取整的几种方法
- Leetcode 236 Lowest Common Ancestor of a Binary Tree
- Swift 中文手册
- iOS多线程中performSelector: 和dispatch_time的不同
- less的使用介绍(一)