HDU - 4333 Revolving Digits(扩展KMP)
生活随笔
收集整理的這篇文章主要介紹了
HDU - 4333 Revolving Digits(扩展KMP)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一個由 n 個數位組成的數字,現在可以通過將其不同的后綴移到前面來組成 n 個新的數字,現在要求出 n 個新數字進行去重后,有多少個新數字分別大于、等于、小于原數字
如:1234進行上述轉移可以得到的四個新數字分別為:1234,4123,3412,2341
題目分析:如果暴力的比較雖然看似只需要枚舉 n 個新的字符串,但是每個字符串的比較還需要花費O(n)的時間,這樣一來一去時間復雜度就到了n*n,我們必須想辦法優化,因為每次比較的答案是后綴和前綴拼接而成的,這不難想到用擴展KMP求出extend數組,這樣就能得到每個后綴與原字符串的最長公共前綴了,如果最長公共前綴的所有數字都是相同的,那么我們只需要比較接下來不相同的一位就可以直接得到其大小關系了,因為是后綴拼接到前綴所得到的答案,我們可以將原串復制一遍拼接到他后面,對于這個兩倍長度的新串直接跑擴展KMP,如果最長公共前綴的長度大于等于原字符串的長度的話,就說明當前的后綴拼到前綴去是與原數字相同的,其他情況就可以直接比較失配的那一位的大小了,至于去重,我們可以一開始對于原串跑出KMP的next數組,利用循環串的性質去重就好了
有個小細節就是擴展KMP的數組記得開兩倍大小,不然會一直TLE
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<set> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e5+100; //字符串長度最大值int Next[N],extend[N],nx[N];char s[N<<1];//預處理計算Next數組 void getNext(char str[]) {int i=0,j,po,len=strlen(str);Next[0]=len; //初始化Next[0]while(str[i]==str[i+1] && i+1<len) i++; Next[1]=i; //計算Next[1]po=1; //初始化po的位置for(i=2;i<len;i++){if(Next[i-po]+i < Next[po]+po) //第一種情況,可以直接得到Next[i]的值Next[i]=Next[i-po];else //第二種情況,要繼續匹配才能得到Next[i]的值{j = Next[po]+po-i;if(j<0) j=0; //如果i>po+Next[po],則要從頭開始匹配while(i+j<len && str[j]==str[j+i]) j++; Next[i]=j;po=i; //更新po的位置}} }//計算extend數組 void EXKMP(char s1[],char s2[]) {int i=0,j,po,len=strlen(s1),l2=strlen(s2);getNext(s2); //計算子串的Next數組while(s1[i]==s2[i] && i<l2 && i<len) i++; extend[0]=i;po=0; //初始化po的位置for(i=1;i<len;i++){if(Next[i-po]+i < extend[po]+po) //第一種情況,直接可以得到extend[i]的值extend[i]=Next[i-po];else //第二種情況,要繼續匹配才能得到extend[i]的值{j = extend[po]+po-i;if(j<0) j=0; //如果i>extend[po]+po則要從頭開始匹配while(i+j<len && j<l2 && s1[j+i]==s2[j]) j++; extend[i]=j;po=i; //更新po的位置}} }void get_next() {int len=strlen(s);nx[0]=-1;int i=0,j=-1;while(i<len){if(j==-1||s[i]==s[j])nx[++i]=++j;elsej=nx[j];} }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){scanf("%s",s);get_next(); int len=strlen(s);int t=1;if(len%(len-nx[len])==0)t=len/(len-nx[len]);for(int i=0;i<len;i++)s[i+len]=s[i];getNext(s);EXKMP(s,s);int ans1=0,ans2=0,ans3=0;for(int i=0;i<len;i++){if(extend[i]>=len)ans2++;else if(s[i+extend[i]]>s[extend[i]])ans3++;else if(s[i+extend[i]]<s[extend[i]])ans1++;}printf("Case %d: %d %d %d\n",++kase,ans1/t,ans2/t,ans3/t);}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 4333 Revolving Digits(扩展KMP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UVA - 11437 Triangle
- 下一篇: HDU - 5157 Harry and