前置知识
哈希,本人认为它是一个密码加密技术,就是加密一个密码所用的东西。在算法中,我们使用它可以减少空间,虽然有可能引起冲突,所以说我们就可以用一些方法来减少冲突的可能。虽然它的部分问题可以用 KMP 解决,但本题还是推荐使用哈希。
算法思路
首先,我们使用单哈希,具体方法只需要用到初始化和查询子串的值,具体方法如下,设常数 ,那么 ,有没有想到什么?对,前缀和!查询子串的方法可以这样:子串 的值为 ,有了这个方法,我们可以 地匹配了。最后贪心的从右侧寻找与左边的相同的数,相同就可以了,不相同就继续查找。
复杂度分析
空间复杂度 ,即 Hash 数组,时间复杂度 ,因为每个字母只便利并且删除一次,可以过。
AC Code:
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int k=131,maxl=1e6+5;
int t,Hash[maxl],power[maxl];
inline int getans(int l,int r){
return Hash[r]-Hash[l-1]*power[r-l+1];
}//查询子串的值
signed main(){
scanf("%llu",&t);
power[0]=1;
for(int i=1;i<=maxl;++i)
power[i]=power[i-1]*k;//初始化次方表
for(int i=1;i<=t;++i){
char s[maxl];
scanf("%s",s+1);
int len=strlen(s+1);
int l=1,r=len,ans=0;
for(int i=1;i<=len;i++)
Hash[i]=Hash[i-1]*k+s[i]-+1;//初始化
while(l<r){
long long f=-1;
for(int i=1;i<=len;++i){
int ll=l+i-1,rr=r-i+1;
if(ll>rr)
break;
if(getans(l,ll)==getans(rr,r)){
f=i;
break;
}
}
if(f==-1){
ans++;
break;
}
ans+=2,l+=f,r-=f;
}
if(l==r)
ans++;
printf("%llu\n",ans);
}
return 0;
}