hdu 4436 str2int 字尾自動機

2021-06-18 09:44:44 字數 1374 閱讀 4046

hdu 4436 str2int (字尾自動機)

題意:給出n個數字,數字很長,用字串讀入,長度總和為10^5。求這n個字串的所有子串(不重複)的和取模2012 。

解題思路:字尾自動機。。因為要處理所有不同的子串,所以想到字尾自動機。將所有的串乙個個建進去,用乙個10去間隔開來。建好之後,我們要統計和了。字尾自動機有這樣乙個性質,從s出發,到達所有節點的路徑的集合,即所有該串的不相同的子串的集合(這個性質為什麼我就不詳細解釋了,想詳細了解的可以找我詳細討論,我也加深下理解),還有另乙個性質,父親的代表串的長度比兒子短(顯而易見,不解釋了)。利用第乙個性質,我們記錄節點的sum[u]表示到u節點的所有子串的和,那麼對於u下面乙個能到達的節點v,sum[v] = sum[u] * 10 + cnt[u] * k  (cnt[u] 表示到達u的路徑數,因為任意一條路徑都可以再添上乙個k,所以用cnt[u] * k),cnt 的維護就是從父親累加過來了。所有節點的sum求完之後,累加即答案。一開始我是用的廣搜,從根開始,如果有兒子就往兒子更新。但是這樣是不對的,有可能兒子的代表串的長度並不是len[u] +1啊,當你將兒子加入到更新佇列中時,此時它的資訊並不完整,因此我們根據第二個性質,給節點排序,父親在前。這樣的話,就可以保證你要用v向下更新時,它的資訊已經是真實的了。

字尾自動機,不錯的資料結構,**簡短,效率高:

#pragma comment(linker, "/stack:1024000000,1024000000")

#include#include#include#includeusing namespace std ;

const int maxn = 111111 ;

int ans ;

int sum[maxn<<1] , cnt[maxn<<1] ;

int pos[maxn<<1] ;

int c[11][maxn<<1] , fa[maxn<<1] , val[maxn<<1] ;

int tot , last ;

bool cmp ( int i , int j )

struct sam

void add ( int k )

} last = np ;

} void init ()

void solve ()

} for ( i = 1 ; i <= tot ; i ++ ) ans = ( ans + sum[i] ) % 2012 ;

}} suf ;

char s[maxn] ;

int main ()

suf.solve () ;

printf ( "%d\n" , ans ) ; }}

/*4620000

411164

782*/

HDU 4436 str2int(字尾自動機)

題意 給出一些數字串,每個數字串可以分成若干數字,比如123可以分成1,2,3,12,23,123。求所有數字串分成的數字的集合的和。思路 字尾自動機 串之間用數字10隔開,建立自動機。節點p和數字j得到的子節點q,q cnt p cnt,q sum p sum 10 p cnt j。const i...

字尾陣列 HDU 4436

做法 首先應用求不同子串的演算法,自然想到字尾陣列,然後就是要統計以非 0 開始的字尾。考慮字尾 akak 1ak 2.an tmp 0 ak 0 tmp i tmp i 1 10 ai 0 sum i sum i 1 tmp i 那麼 以 am開始的字首和就是 sum n sum m 1 tmp ...

hdu4436 字尾自動機

題解 求多個字串能夠構成多少種數然後把這些數去重後加起來,字尾自動機有個性質就是路徑數就等於不同子串個數,然後怎麼把多個字串拼接呢,兩個字串中間加入乙個你不會用的字元,因為這樣可以保證我到時候路徑不會走這條 include include include include include includ...