名校聯賽DAY.2A層第一題passward題解
阿新 • • 發佈:2017-08-07
傳說 legend class blog col center isp using src
問題 A: Passward
時間限制: 1 Sec 內存限制: 512 MB題目描述
你來到了一個廟前,廟牌上有一個僅包含小寫字母的字符串 s。
傳說打開廟門的密碼是這個字符串的一個子串 t,並且 t 既是 s 的前綴又是 s的後綴並且還在 s 的中間位置出現過一次。
如果存在這樣的串,請你輸出這個串,如有多個滿足條件的串,輸出最長的那一個。
如果不存在這樣的串,輸出"Just a legend"(去掉引號)。
輸入格式:
僅一行,字符串 s。
輸出格式:
如題所述
樣例輸入
fixprefixsuffix
樣例輸出:
fix
數據範圍:
對於 60%的數據, s 的長度<=100
對於 100%的數據, s 的長度<=100000
不得不說一下,這道題真的挺水的,當時考試時就是奔60分去的,誰知道一不小心滿分了,數據水,不卡我。
他們說這是KMP裸題,我當時也想到了這點,然而上次打KMP還是在一個半月前,有點忘,不敢直接打KMP,因此直接去打的HASH+MP(fail數組)+鏈表的暴力。
首先先預處理出hash,mp的fail,鏈表,因為與前綴後綴相等的單詞第一個字母一定和首字母相同,因此我們大可對與首字母相同的位置建一個鏈表,暴力擼一遍即可,真的挺無聊的。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4View Code#include<cstring> 5 #include<queue> 6 #include<algorithm> 7 #include<queue> 8 #include<map> 9 #include<cmath> 10 using namespace std; 11 char s[100005]; 12 int n,a[100005]; 13 int p=12345; 14 unsigned long long xp[100005]; 15 map<int,unsigned long long> ha; 16 int hz[100005],qz[100005],fl[100005]; 17 int main(){ 18 scanf("%s",s); 19 n=strlen(s); 20 for(int i=0;i<n;i++) 21 { 22 a[i+1]=s[i]-‘a‘+1; 23 } 24 xp[0]=1; 25 for(int i=1;i<=n+2;i++) 26 xp[i]=xp[i-1]*p; 27 for(int i=n;i>0;i--) 28 ha[i]=ha[i+1]*p+a[i]; 29 int nw=1; 30 for(int i=2;i<=n;i++) 31 { 32 if(a[i]==a[1]) 33 { 34 hz[nw]=i; 35 qz[i]=nw; 36 nw=i; 37 } 38 } 39 for(int i=2,j=0;i<=n;i++) 40 { 41 while(j&&a[i]!=a[j+1]) j=fl[j]; 42 if(a[i]==a[j+1]) j++; 43 fl[i]=j; 44 } 45 nw=n-fl[n]+1; 46 int ans=0; 47 while(nw) 48 { 49 50 int l=n-nw+1; 51 unsigned long long hs=ha[1]-ha[l+1]*xp[l]; 52 unsigned long long hss=ha[nw]-ha[n+1]*xp[l]; 53 if(hs!=hss) 54 { 55 nw=hz[nw]; 56 continue; 57 } 58 bool yx=1; 59 60 for(int i=hz[1];i<nw;i=hz[i]) 61 { 62 unsigned long long hh=ha[i]-ha[i+l]*xp[l]; 63 if(hh==hs) 64 { 65 ans=l; 66 yx=0; 67 break; 68 } 69 } 70 if(!yx) 71 break; 72 nw=hz[nw]; 73 } 74 if(nw) 75 { 76 for(int i=0;i<ans;i++) 77 cout<<s[i]; 78 } 79 else 80 { 81 printf("Just a legend\n"); 82 } 83 // while(1); 84 return 0; 85 }
名校聯賽DAY.2A層第一題passward題解