SPOJ LCS2 字尾自動機

2021-12-30 01:07:56 字數 1297 閱讀 7832

給多個字串,問最長公共子串。

最長公共子串用字尾自動機還是很方便的,首先的話,有乙個非常重要的字尾自動機性質一定要明確,字尾自動機乙個點的par一定是這個點代表的所有字元子串的公共字尾。了解了這一點,我們便可以構造字尾自動機,然後進行匹配。

在匹配的過程中,如果可以成功轉移,直接轉移並且把記錄的長度++就可以了。如果不可以成功轉移,那麼就需要去進行失配匹配。這時候字尾自動機的方便性就很好的體現出來了,如果失配的話,直接轉移到par點就可以了,因為par點是這個點所有子串的公共最大字尾,因此轉移到par點是最合理的選擇。這樣的話,如果可行的話,就把匹配長度賦為len[par]+1。否則繼續進行失配匹配。

上述講解是針對lcs那道題的,這道題相比於lcs又麻煩一點。這道題是求多個串的公共子串。那麼我們首先需要記錄一下轉移到每個點的最大匹配長度,這裡需要注意的是,在匹配的過程中有可能沒有經過par點,但是由於實際上字串是包含par點的,所以需要處理一下,將經過的par點的匹配長度賦為len[par]。然後我們要針對每乙個點選擇最小的匹配長度,這樣才是所有字串的公共子串。

最後的話,我們選擇所有公共匹配長度中最大的作為結果就可以了。

需要對匹配過程十分注意,如果失配到0以後,u的值要賦為1(也就是root)。如果賦為0的話,會wa on test 3。

#include

#define up(i,l,h) for(int i=l;i=l;i--)

#define w(a) while(a)

#define mem(a,b) memset(a,b,sizeof(a))

#define ll long long

#define inf 0x3f3f3f3f

#define maxn 200050

#define mod 1000000007

#define eps 1e-3

using namespace std;

char s[maxn];

struct suffixauto

void init(int x)

void extend(int c)

}last=np;

}void countsort()

void find(char *st) else else

}mx[u]=max(mx[u],now);

}down(i,allc+1,1) if(mx[id[i]]) mx[par[id[i]]]=len[par[id[i]]];

up(i,1,allc+1) {

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

// cout<

SPOJ LCS2 字尾自動機

題意 求多個串的lcs 思路 跟上題一樣的東西 只不過多加乙個臨時的dp陣列來儲存所有的狀態的最小值 然後求所有子串的最大值就好了 include include include include include include include include include include incl...

SPOJ LCS2 字尾自動機

題目傳送門 題目大意 還是求字串的最長公共子串,只不過這次是n個串。思路 先把第乙個串丟到sam裡面去,然後每乙個串都和前面那個串做一次最長公共子串的匹配。我們現在把sam裡面的其中乙個狀態記做 p 這個 p 其實就代表了 right 集合相同的所有子串,我們要記錄每乙個狀態下的最大匹配長度 通俗的...

spoj LCS 字尾自動機

琦不會字尾自動機 是以前太浪了 所以所有東西都留到了noi前來學 馬上狗牌退役了tat 心塞qwq 題目大意 給出兩個串a,b,求a b的最長公共子串 對a建字尾自動機,然後用b去匹配,若能匹配上就轉移到兒子,否則沿著parent樹向上跳 include include include includ...