SUFEQPRE - Suffix Equal Prefix

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",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\n",++cnt,ans-1);//记得长度严格小于N
    }
} 

 有何意见,请在下方评论谢谢!

posted @ 2019-08-26 10:06  Coder_cjh  阅读(277)  评论(0编辑  收藏  举报