日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

牛客多校4 - Count New String(序列自动机+广义后缀自动机)

發(fā)布時(shí)間:2024/4/11 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客多校4 - Count New String(序列自动机+广义后缀自动机) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目鏈接:點(diǎn)擊查看

題目大意:

題目分析:首先觀察到集集合 A 中那個(gè)套娃的表示,外層的范圍是 [ x1 , y1 ] ,內(nèi)層是 [ x2 , y2 ] ,而內(nèi)層的定義域?qū)嶋H上是包含在外層的定義域內(nèi)的,這樣外層的函數(shù) f 其實(shí)是不起作用的,因?yàn)閮?nèi)層的函數(shù) f 已經(jīng)按照規(guī)則將區(qū)間集合 A 中 [ x1 , y1 ] 內(nèi)的每個(gè)元素按照規(guī)則轉(zhuǎn)換完畢了,再進(jìn)行一次相同的轉(zhuǎn)換,則就變的可有可無(wú)了,換句話說(shuō),每一個(gè) f( S , x1 , y1 ) 實(shí)質(zhì)上表示為字符串 s 的每個(gè)子串經(jīng)過(guò) f 函數(shù)轉(zhuǎn)換后的字符串,這樣題意就變成了求所有子串經(jīng)過(guò) f 函數(shù)的轉(zhuǎn)換后,有多少個(gè)本質(zhì)不同的字符串

上面轉(zhuǎn)換后的題意還不夠直接,通過(guò)觀察可以發(fā)現(xiàn),假設(shè)字符串 s 在經(jīng)過(guò) f 函數(shù)的轉(zhuǎn)換后,得到新的字符串記為 ss ,不難看出字符串 s 的一個(gè)前綴在經(jīng)過(guò) f 函數(shù)的轉(zhuǎn)換后,得到的仍然是 ss 的前綴

參考后綴與子串的關(guān)系,可以將所有的子串表示為任意一個(gè)后綴的前綴,同樣題意轉(zhuǎn)換為了所有經(jīng)過(guò) f 函數(shù)轉(zhuǎn)換后的后綴中,有多少個(gè)本質(zhì)不同的子串

這樣題意就轉(zhuǎn)換為了求 f( S , i , n ) ,i ∈ [ 1 , n ] ,求 n 個(gè)串中本質(zhì)不同的子串,這個(gè)可以借助廣義后綴自動(dòng)機(jī)來(lái)完成,但是如果暴力為 n 個(gè)串建立 sam 的話,時(shí)空復(fù)雜度都會(huì)爆掉,再根據(jù) f 函數(shù)的性質(zhì)來(lái)考慮,可以發(fā)現(xiàn),因?yàn)樽址拇笮?10,所以任意一個(gè)位置的字符,至多會(huì)被更新 9 次,最極端的情況下,假設(shè)字符串為 dcbaaa...aaa,后綴的長(zhǎng)度從小到大可以表示為:

  • a
  • aa
  • aaa
  • ......
  • aaa...aaa
  • bbbb...bbb
  • ccccc...ccc
  • ddddd...ddd
  • 這是最極端的情況,這樣整體建立廣義 sam 的時(shí)空復(fù)雜度也不會(huì)超過(guò) 10N

    在建立廣義 sam 時(shí),可以借助序列自動(dòng)機(jī)來(lái)實(shí)現(xiàn),普通的序列自動(dòng)機(jī) nx[ i ][ j ] 記錄的是位置 i 后(包括)首次出現(xiàn)字母 j 的位置,在本題中需要轉(zhuǎn)換為:nx[ i ][ j ] 表示為記錄位置 i 后(包括)首次大于等于字母 j 的位置,這樣對(duì)于第 i 個(gè)位置的字母 j 來(lái)說(shuō),只需要暴力更新一下 [ i , nx[ i ][ j ] - 1 ] 就好了,nx[ i ][ j ] 往后的位置都可以直接從前面維護(hù)的 trie 樹中拉下來(lái)繼續(xù)用

    時(shí)空復(fù)雜度都是 10N

    代碼:
    ?

    #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;char s[N];int tot,last,id[N],nx[N][10];struct Node {int ch[10];int fa,len; }st[N<<1];inline int newnode() {tot++;for(int i=0;i<10;i++)st[tot].ch[i]=0;st[tot].fa=st[tot].len=0;return tot; }void add(int x) {int p=last;//if(st[p].ch[x]){int q=st[p].ch[x];if(st[q].len==st[p].len+1)last=q;else{int np=last=++tot;st[np].len=st[p].len+1;st[np].fa=st[q].fa;st[q].fa=np;for(int i=0;i<10;i++)st[np].ch[i]=st[q].ch[i];while(st[p].ch[x]==q)st[p].ch[x]=np,p=st[p].fa;}return;}//int np=last=++tot;st[np].len=st[p].len+1;while(p&&!st[p].ch[x])st[p].ch[x]=np,p=st[p].fa;if(!p)st[np].fa=1;else{int q=st[p].ch[x];if(st[p].len+1==st[q].len)st[np].fa=q;else{int nq=++tot;st[nq]=st[q]; st[nq].len=st[p].len+1;st[q].fa=st[np].fa=nq;while(p&&st[p].ch[x]==q)st[p].ch[x]=nq,p=st[p].fa;//向上把所有q都替換成nq}} }void init() {last=1;tot=0;newnode(); }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);init();scanf("%s",s+1);int n=strlen(s+1);for(int i=0;i<10;i++)nx[n+1][i]=n+1;for(int i=n;i>=1;i--)//nx[i][j]:第i個(gè)位置(包括)后首次出現(xiàn)大于等于j的位置 {for(int j=0;j<10;j++)nx[i][j]=nx[i+1][j];nx[i][s[i]-'a']=i;for(int j=8;j>=0;j--)nx[i][j]=min(nx[i][j],nx[i][j+1]);}id[n+1]=last;for(int i=n;i>=1;i--){int pos=nx[i+1][s[i]-'a'];last=id[pos];for(int j=i;j<pos;j++)add(s[i]-'a');id[i]=last;}LL ans=0;for(int i=1;i<=tot;i++)ans+=st[i].len-st[st[i].fa].len;printf("%lld\n",ans);return 0; }

    ?

    總結(jié)

    以上是生活随笔為你收集整理的牛客多校4 - Count New String(序列自动机+广义后缀自动机)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。