【题解】 Codeforces Edu41 F. k-substrings (字符串Hash)
生活随笔
收集整理的這篇文章主要介紹了
【题解】 Codeforces Edu41 F. k-substrings (字符串Hash)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題面戳我
Solution
- 我們正著每次都要枚舉從長(zhǎng)到短,時(shí)間復(fù)雜度承受不了,但是我們可以發(fā)現(xiàn)一個(gè)規(guī)律,假設(shè)某次的答案為\(x\),那么這個(gè)字符串為\(A+X+B\)組成,無(wú)論中間的\(X\)是重疊還是空余的,我們都可以發(fā)現(xiàn),這個(gè)字符串可以改成\(a+A'+X+B'+b\),所以下一次砍掉兩邊,這個(gè)\(A'\)中沒(méi)有\(a\)與\(B'\)匹配,\(B'\)中同理沒(méi)有\(b\)與\(A'\)匹配,所以公共串長(zhǎng)度至少\(-2\)。
- 有了上面那個(gè)性質(zhì),我們?cè)俚怪鴣?lái)做,我們把砍掉兩邊改成在兩邊加上兩個(gè)字符,那么這次答案,至多是上次答案\(+2\),那么答案就只能從\(lastans+2,lastans,\cdots,1\)中查找,我們?nèi)绻袛嗟揭粋€(gè)答案符合前綴和后綴一樣,我們就可把這個(gè)數(shù)作為答案,直接\(break\)即可,長(zhǎng)度\(1\)的子串前綴和后綴都沒(méi)有答案就是\(-1\)。
- 我們來(lái)驗(yàn)證下時(shí)間復(fù)雜度的正確性,因?yàn)槲覀兠看味际菑?span id="ozvdkddzhkzd" class="math inline">\(lastans+2\),開(kāi)始然后向后減,其實(shí)就與\(KMP\)一樣(我不會(huì)),減的次數(shù)由加的次數(shù)決定,然后我們加的次數(shù)不會(huì)多于\(n/2+1\),忽略常數(shù),再加上\(Hash\),所以我們就可以證明時(shí)間復(fù)雜度大概是\(O(n)\)的了
- 判斷字符串相同用\(Hash\)
Code
//It is coded by ning_mew on 7.23 #include<bits/stdc++.h> #define LL long long using namespace std;const int maxn=1e6+7;int n; char ch[maxn]; LL MOD[3]={19260817,20000909,19491001}; LL Hash[3][maxn],Pow[3][maxn]; int ans[maxn];bool check(int s,int len){int mid,t;if(n%2){mid=(n+1)/2;t=2*mid-s;}else {mid=n/2;t=mid-s+mid+1;}for(int i=0;i<3;i++){int box1=((Hash[i][s+len-1]-Hash[i][s-1]*Pow[i][len])%MOD[i]+MOD[i])%MOD[i];int box2=((Hash[i][t]-Hash[i][t-len]*Pow[i][len])%MOD[i]+MOD[i])%MOD[i];if(box1!=box2)return false;}return true; } void work1(){ans[(n+1)/2]=-1;for(int i=(n+1)/2-1;i>=1;i--){//cout<<"----------------------"<<endl;ans[i]=-1;for(int k=ans[i+1]+2;k>=1;k-=2){//cout<<k<<endl;if(check(i,k)){ans[i]=k;break;}}}for(int i=1;i<=(n+1)/2;i++){printf("%d ",ans[i]);} printf("\n"); } void work2(){if(ch[n/2]==ch[n/2+1])ans[n/2]=1;else ans[n/2]=-1;for(int i=n/2-1;i>=1;i--){ans[i]=-1;for(int k=ans[i+1]+2;k>=1;k-=2){//cout<<k<<endl;if(check(i,k)){ans[i]=k;break;}}}for(int i=1;i<=n/2;i++){printf("%d ",ans[i]);} printf("\n"); } int main(){scanf("%d",&n);scanf("%s",ch+1);for(int j=0;j<3;j++){Pow[j][0]=1;for(int i=1;i<=n;i++){Hash[j][i]=(Hash[j][i-1]*27+ch[i]-'a')%MOD[j];Pow[j][i]=Pow[j][i-1]*27%MOD[j];}}if(n%2)work1();else work2();return 0; }博主蒟蒻,隨意轉(zhuǎn)載。但必須附上原文鏈接:http://www.cnblogs.com/Ning-Mew/,否則你會(huì)場(chǎng)場(chǎng)比賽爆0!!!
轉(zhuǎn)載于:https://www.cnblogs.com/Ning-Mew/p/9356955.html
總結(jié)
以上是生活随笔為你收集整理的【题解】 Codeforces Edu41 F. k-substrings (字符串Hash)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java知识点梳理——继承
- 下一篇: 理财的风险是什么