並沒有什麼想說的,但是要保持格式=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 ...