P5341-[TJOI2019]甲苯先生和大中锋的字符串【SAM】
生活随笔
收集整理的這篇文章主要介紹了
P5341-[TJOI2019]甲苯先生和大中锋的字符串【SAM】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P5341
題目大意
給出一個字符串,求出現次數恰好為kkk的子串中,出現最多的長度。
解題思路
先根據TTT構建一個SAMSAMSAM,對于一個endposendposendpos類中,所有出現串的長度一定是一個連續的區間。
所以我們直接計算出每個endposendposendpos類的大小,如果是kkk,就差分讓[lenfx+1,lenx][len_{f_x}+1,len_{x}][lenfx??+1,lenx?]加111。
時間復雜度O(n)O(n)O(n)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=2e5+10; ll T,n,k,a[N],c[N],rk[N],num[N]; ll cnt,last,fa[N],ch[N][26],len[N]; char s[N]; void insert(ll c){ll p=last,np=last=++cnt;len[np]=len[p]+1;num[cnt]++;for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;if(!p)fa[np]=1; else{ll q=ch[p][c];if(len[p]+1==len[q])fa[np]=q;else{ll nq=++cnt;len[nq]=len[p]+1;memcpy(ch[nq],ch[q],sizeof(ch[nq]));fa[nq]=fa[q];fa[q]=fa[np]=nq;for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;}}return; } int main() {scanf("%lld",&T);while(T--){last=cnt=1;memset(ch[1],0,sizeof(ch[1]));scanf("%s",s+1);n=strlen(s+1);for(ll i=1;i<=n;i++)insert(s[i]-'a'),a[i]=c[i]=0;scanf("%lld",&k);bool flag=0;for(ll i=1;i<=cnt;i++)c[len[i]]++;for(ll i=1;i<=n;i++)c[i]+=c[i-1];for(ll i=1;i<=cnt;i++)rk[c[len[i]]--]=i;for(ll i=cnt;i>=1;i--)num[fa[rk[i]]]+=num[rk[i]];for(ll i=2;i<=cnt;i++)if(num[i]==k)a[len[i]]++,a[len[fa[i]]]--,flag=1;for(ll i=n;i>=0;i--)a[i]+=a[i+1];ll mark=0;a[0]=0;for(ll i=1;i<=n;i++)if(a[i]>=a[mark])mark=i;if(!flag)printf("-1\n");else printf("%lld\n",mark);for(ll i=0;i<=cnt;i++)num[i]=fa[i]=len[i]=0,memset(ch[i],0,sizeof(ch[i]));} }總結
以上是生活随笔為你收集整理的P5341-[TJOI2019]甲苯先生和大中锋的字符串【SAM】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么建小程序商城(怎么建小程序商城店铺)
- 下一篇: 怎么组建企业网站(怎么组建企业网站链接)