SPOJ1812 LCS2 字尾自動機

2021-08-14 17:42:27 字數 1630 閱讀 7405

並沒有什麼想說的,但是要保持格式=w=

spoj - lcs2傳送門

給出n個字串(n不超過10,每個串長不超過100000),求出這n個字串的最長公共子串

(tip:子串是連續的,子串行是不連續的)

輸入格式:

一共n行,每行包含乙個字串

輸出格式:

輸出一行乙個整數,表示最長公共子串

這是一道字尾自動姬的基礎應用題=w=

首先拿乙個串來建立字尾自動姬,然後用其它的串在這個自動姬上匹配。

匹配的時候維護乙個cnt表示當前匹配的長度。如果能夠匹配就一直走,並且cnt加一;不能走就跳parent邊,直到跳到乙個有當前字元轉移邊的節點,然後把cnt設為當前節點的max_length,繼續匹配。匹配完之後,自底向上更新每個節點的「節點當前最大匹配長度」(注意匹配長度不能超過max_length),然後用「節點當前最大匹配長度」去更新「節點全域性匹配長度」。最後在這個 全域性匹配長度 裡取個max就是答案

關於跳parent的正確性,因為right集合之間是互相包含的,所以如果能走到當前節點,就表示至少min_len的長度被匹配上了,而parent的max_len是當前節點的min_len-1,所以parent也一定能匹配,而且可以匹配完。

當前串最大匹配長度,只是當前這乙個串在字尾自動姬上跑出來的匹配長度,而要求的是所有串的公共子串,因此就定義了「節點當前最大匹配長度」和「節點全域性匹配長度」這兩個陣列

#include 

#include

#include

using namespace std ;

int n , id_c , ans ;

int max[200005] , min[200005] ;

char ss[100005] ;

struct nodew[200005] , *tw = w , *root , *last ;

void newnode( node *&nd , int len )

void insert( char cc )}}

last = nd ;

}int tp[200005] , sa[200005] ;

void rsort()

void run()

max[ nd->id ] = max( max[ nd->id ] , len ) ;

// printf( "max[%d] is %d\n" , nd->id , max[ nd->id ] ) ;

}for( int i = id_c ; i > 1 ; i -- )

for( int i = 2 ; i <= id_c ; i ++ )

min[i] = min( min[i] , max[i] ) ;

}int main()

for( int i = 2 ; i <= id_c ; i ++ )

ans = max( min[i] , ans ) ;

printf( "%d" , ans == min[0] ? 0 : ans ) ;

}

SPOJ 1812 LCS2 字尾自動機 DP

題意 求多個串 10的最長連續子串 乙個串建sam,然後其他串在上面走 每個狀態記錄所有串在這個狀態的公共子串的最小值 乙個串在上面走的時候記錄與每個狀態公共子串的最大值,注意出現次數向父親傳遞,乙個狀態能到達說明了suffix link指向的狀態可以取到最大子串,這一步對val後基數排序然後倒著更...

SPOJ 1812 LCS2 字尾自動機 DP

題意 求多個串 10的最長連續子串 乙個串建sam,然後其他串在上面走 每個狀態記錄所有串在這個狀態的公共子串的最小值 乙個串在上面走的時候記錄與每個狀態公共子串的最大值,注意出現次數向父親傳遞,乙個狀態能到達說明了suffix link指向的狀態可以取到最大子串,這一步對val後基數排序然後倒著更...

SPOJ 1811 LCS 字尾自動機

題意 求兩個串的最大連續子串 乙個串建sam,另乙個串在上面跑 注意如果走了suffix link,sum需要更新為t u val 1 suffix link有點像失配吧,當前狀態s走不了了就到suffix link指向的狀態fa上去,fa是s的字尾所以是可行的,並且有更多走的機會 include ...