题意:给你一个字符串(sl<=1e6),问每一个起点到1和终点到sl距离相等的子串的最长不等于串长的border。
标程:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 typedef long long ll; 6 const int can=31; 7 const int mod=20030321; 8 const int N=1000005; 9 int ha[N],pow[N],n,ans[N],l,r,len,cnt; 10 char s[N]; 11 int S(int x,int l) 12 {return ((ll)ha[x+l-1]-(ll)ha[x-1]*pow[l]%mod+mod)%mod;} 13 int main() 14 { 15 scanf("%d%s",&n,s+1); 16 pow[0]=1; 17 for (int i=1;i<=n;i++) pow[i]=(ll)pow[i-1]*can%mod; 18 for (int i=1;i<=n;i++) ha[i]=((ll)ha[i-1]*can%mod+(s[i]-'a'+1))%mod; 19 if (n&1) l=r=n/2+1;else l=n/2,r=l+1;len=1; 20 while (r<=n) 21 { 22 while (len!=-1&&S(l,len)!=S(r-len+1,len)||len>=r-l+1) len-=2; 23 ans[++cnt]=len; 24 l--,r++; len+=2; 25 } 26 for (int i=cnt;i>=1;i--) printf("%d ",ans[i]); 27 return 0; 28 }
题解:hash+单调性
对于每一个串二分+hash?这样的答案并没有单调性。
但是(分析数据)经过有理有据的推导,发现所有这样的串的答案是具有单调性的。
对于一个串,如果在它的两边各加一个字符,那么它的border长度最多+2。
证明:
比如现在完成一个串A....B(A,B都是字符块,并且为该串的最长border)
左右各扩展:xA....By
可以证明最优情况下的匹配是xAz...gBy,不会出现xAC...DBy(C,D是长度>1的字符块)
如果存在xAC=DBy.那么提取C的最后一个字母=y,D的第一个字母=x,即xACy=xDBy。
所以AC=DB,不满足A,B是最长border。
然后就直接hash比较即可。
时间复杂度O(n)。