Codeforces 126B. Password(KMP,DP)
阿新 • • 發佈:2018-11-09
Codeforces 126B. Password
題意:一個字串,找出最長的子串t,它既是字首又是字尾,還出現在中間。輸出t,不存在則輸出Just a legend。
思路:利用KMP演算法處理出next陣列,由next陣列的意義可以知道i為尾的最長相同字首字尾。則ne[n-1],ne[ne[n-1]],ne[ne[ne[n-1]]]......均為可能的解,且長度遞減,為了高效的逐一驗證,則需要預處理出整個字串有多少個與該字首相同的子串。用到DP思想,cnt[next[i]]+=cnt[i],倒著更新一遍,即可處理出上述資訊。那麼cnt大等於3的字首,均為可行解
程式碼:
#include<iostream> #include<cstdio> #include<algorithm> #include<string> #define dd(x) cout<<#x<<" = "<<x<<" " #define de(x) cout<<#x<<" = "<<x<<"\n" #define pb push_back #define mp make_pair #define fi first #define se second #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; typedef long double ld; const int maxn=1e6+10,mod=1e9+7,INF=0x3f3f3f3f; char s[maxn]; int ne[maxn],cnt[maxn]; void init() { ne[0]=-1; for (int i=1;s[i];++i) { int j=ne[i-1]; while (s[j+1]!=s[i]&&j>=0) j=ne[j]; if (s[j+1]==s[i]) ne[i]=j+1; else ne[i]=-1; } } int main() { scanf("%s",s); init(); int n=strlen(s); for (int i=0;i<n;++i) cnt[i]=1; for (int i=n-1;i;--i) cnt[ne[i]]+=cnt[i]; for (int i=ne[n-1];i!=-1;i=ne[i]) { if (cnt[i]>=3) { for (int j=0;j<=i;++j) printf("%c",s[j]); return 0; } } printf("Just a legend"); return 0; }