1. 程式人生 > >hdu3374 kmp+最小表示法

hdu3374 kmp+最小表示法

small clu 個數 ext 表示 abcde precision pre mes

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

abcder
aaaaaa
ababab

Sample Output

1 1 6 1
1 6 1 6
1 3 2 3
題意:找出一個字符串的循環列中最小和最大的那個字符串,並求出格數
題解:個數就是最小循環數,用kmp的next數組即可,然後用字符串的最小表示法求,最大的同理wa點:剛開始想直接暴力結果mle,莫名其妙,我以為應該是tle,結果改用kmp了之後,直接暴力求最小還是tle,

最後實在沒辦法看的最小表示法,還有一點就是自己腦殘,寫成了ans=(slen%ans ? ans:slen/ans)不能整除明明是1啊!!
不過還是沒搞懂為啥不能直接循環求最小,時間復雜度明明是一樣的,最小表示法時間復雜度也是O(n)啊
技術分享
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define
ll long long #define mod 10007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-9; const int N=1000000+5,maxn=(1<<18)-1,inf=0x3f3f3f3f; int Next[N],slen; string str; void getnext() { int k=-1; Next[0]=-1; for(int i=1;i<slen;i++) { while(k>-1&&str[k+1]!=str[i])k=Next[k]; if(str[k+1]==str[i])k++; Next[i]=k; } } int solve(bool flag) { int i=0,j=1,k=0; while(i<slen&&j<slen&&k<slen){ int t=str[(i+k)%slen]-str[(j+k)%slen]; if(!t)k++; else { if(flag)t>0 ? i=i+k+1:j=j+k+1; else t<0 ? i=i+k+1:j=j+k+1; if(i==j)j++; k=0; } } return min(i,j); } int main() { ios::sync_with_stdio(false); cin.tie(0); // cout<<setiosflags(ios::fixed)<<setprecision(2); while(cin>>str){ slen=str.size(); getnext(); int ans=slen-Next[slen-1]-1; ans=(slen%ans ? 1:slen/ans); cout<<solve(1)+1<<" "<<ans<<" "<<solve(0)+1<<" "<<ans<<endl; } return 0; }
View Code

hdu3374 kmp+最小表示法