My blog
题目简述
给你一个字符串 SS ,判断有多少个前缀也是后缀
输入格式
第一行T,有T组数据 第2~T+1行,T个字符串
输出格式
Case (Number): ans
数据范围
1<=|S|<=10^6
Solution
Step 1:HashStep 1:Hash
看到这道题很容易想到hash操作,也就是暴力解法,算一算时间是 O(TN) ,显然过不去,但还是写了
#include<iostream>
#include<cstdio>
#include<cstring>
//#pragma GCC optimize("O2")
//#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast") 加了依然不可做
using namespace std;
#define max(a,b) (a>b?a:b)
unsigned long long hs[1000005],p[1000005];
int maxn=1,T,cnt,ans;
char s[1000005];
int main(){
while(~scanf("%s", s+1)){
p[0]=1;
int n=strlen(s+1);
for(int i=1;i<=n;i++)hs[i]=hs[i-1]*131+(s[i]-'a'+1);
for(int i=maxn;i<=n;i++)p[i]=p[i-1]*131;
ans=0;
for(int i=1;i<n;i++)
if(hs[i]==hs[n]-hs[n-i]*p[i])//hash操作
printf("%d ",i);
printf("%d
",n);
maxn=max(n,maxn);
}
}
TLE
Step 2
经过深(yi)思(fan)熟(xia)虑(gao)之后,我们发现,最长的公共前后缀是可以确定的,我们只要求出最长的,再左右横跳就可以得到解法了:
KMP
利用 KMPKMP 的nxt数组,在 period中的思想类似,可以在 O(N) 的时间而不是 O(3N) ,可以更加高效地解决
#include<bits/stdc++.h>
#define max(a,b) (a>b?a:b)
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
using namespace std;
int maxn=1,T,cnt,ans;
char s[1000005];
int nxt[1000005];
int main(){
scanf("%d",&T);
while(T--){
scanf("%s", s+1);
int n=strlen(s+1);
nxt[1]=0;
for(int i=2,j=0;i<=n;i++){
while(j>0&&s[i]!=s[j+1])j=nxt[j];
if(s[i]==s[j+1])j++;
nxt[i]=j;
}
int ans=0;
for(int i=n;i;i=nxt[i])++ans;//左右横跳
printf("Case %d: %d
",++cnt,ans-1);//记得长度严格小于N
}
}
有何意见,请在下方评论谢谢!