问题 A: Passward
时间限制: 1 Sec 内存限制: 512 MB题目描述
你来到了一个庙前,庙牌上有一个仅包含小写字母的字符串 s。
传说打开庙门的密码是这个字符串的一个子串 t,并且 t 既是 s 的前缀又是 s 的后缀并且还在 s 的中间位置出现过一次。
如果存在这样的串,请你输出这个串,如有多个满足条件的串,输出最长的那一个。
如果不存在这样的串,输出"Just a legend"(去掉引号)。
输入格式:
仅一行,字符串 s。
输出格式:
如题所述
样例输入
fixprefixsuffix
样例输出:
fix
数据范围:
对于 60%的数据, s 的长度<=100
对于 100%的数据, s 的长度<=100000
输入
做这道题时好迷啊。。首先,可以用HASH逐位比较,其次可以用KMP求出next从尾部向前找,然而,联考时。。我打的大模拟,暴力枚举结果AC了。。数据太水了。。
暴力押正解,乱搞保平安。。(安慰ljy QWQ)
我的暴力
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<iostream> #define ll long long using namespace std; int read() { int sum=0,f=1;char x=getchar(); while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();} while(x>='0'&&x<='9'){sum=sum*10+x-'0';x=getchar();} return sum*f; } char s[100005]; int len,nex[100005]; int get(int k,int j) { if(j==len-1)return 0; for(int i=1;i<=k;i++) { if(s[len-i]!=s[k-i]) return 0; } return 1; } int main() { freopen("fool.in","r",stdin); freopen("fool.out","w",stdout); int n; cin>>n; while(n--) { scanf("%s",s); len=strlen(s); int p=-1; for(int i=1;i<len;i++) { if(s[i]==s[0]) { int j=i,k; while(j<len&&s[j]==s[j-i]) { j++; k=j-i+1; if(get(k,j))p=max(p,k); } if(j!=len)j--; k=j-i+1; if(get(k,j))p=max(p,k); } } if(p==-1) {printf("--- ");return 0;} for(int i=0;i<p;i++) printf("%c",s[i]); printf(" "); } }正解
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int sj=100010; char s[sj]; int len,nt[sj]={0},p; bool cx[sj]={0}; void gn() { nt[1]=nt[0]=0; for(int i=2,k=0;i<=len;i++) { while(k&&s[i-1]!=s[k]) k=nt[k]; if(s[i-1]==s[k]) k++; nt[i]=k; if(i!=len) cx[nt[i]]=1; } } int main() { //freopen("t1.txt","r",stdin); freopen("fool.in","r",stdin); freopen("fool.out","w",stdout); scanf("%d",&p); for(int l=1;l<=p;l++) { scanf("%s",s); len=strlen(s); memset(cx,0,sizeof(cx)); gn(); int jg=nt[len]; while(jg&&!cx[jg]) jg=nt[jg]; if(jg==0) printf("---"); else for(int i=0;i<jg;i++) printf("%c",s[i]); printf(" "); } //while(1); return 0; }