洛谷 P2322 最短母串問題 狀壓 AC自動機

2021-09-26 09:49:56 字數 1633 閱讀 9502

題目大意:給你n個串,讓你求包含這n個串的最短母串

首先,看到多串,就大概知道要用ac自動機了。然後再想,我們怎麼將每個串加入到我們所求的母串上面去。雖然n<12,但是我們無法對每一種情況進行dfs,所以這種想法需要拋棄。

在trie樹上,我們肯定需要遍歷每乙個節點,那麼我們可以對每乙個單詞的結尾進行乙個標記。怎麼標記呢?(注意了,狀壓開始)我們對第i個單詞的結尾建立乙個state陣列,state [now] = 1<<(i-1) ,即當前節點的編號now下,記錄乙個狀態 2^(i-1),至於為什麼是這個值,我們之後會有妙用。

之後我們在進行ac自動機的fail指標的建立的時候,順便也把state的值傳下去。

接著,就進行答案的bfs啦

我們需要開兩個佇列,乙個記錄節點,乙個記錄當前的狀態,在開乙個vis二維陣列,vis[i] [j] 代表到第i個節點時處於 j 狀態時候,是否之前來過。用乙個st變數代表當前的狀態

在bfs的時候,我們每到乙個節點,就將st狀態 or 該節點的state值(st | state[now]),記為當前到達此節點的狀態,然後我們用vis陣列存下來,記錄為已到過,直到最後 st==1《注意這裡的狀壓轉換是利用位運算的,0|1=1,1|0=1,1|1=0,0|0=0

所以每次 or 就代表有乙個單詞加入了

上**:

#include

using namespace std;

#define ll long long

const

int maxn=

605;

int n,state[maxn]

,vis[maxn][1

<<12|

1],tot=

0,cnt1=

0,cnt2=0;

int trie[maxn][26

],fail[maxn]

,ans[

6500000

],fa[

6500000];

char str[13]

[51],anstr[maxn]

;void

build

(char stt,

int p)

state[root]|=

1<<

(p-1);

//為什麼這裡是|,是為了保證多個相同的單詞存在同乙個狀態裡

}void

build_ac()

else

trie[x]

[i]=trie[fail[x]

][i];}

}void

getans()

return;}

for(

int i=

0;i<

26;i++)if

(!vis[trie[now]

[i]]

[st|state[trie[now]

[i]]])

++id;}}

intmain()

build_ac()

;getans()

;for

(int i=cnt2;i>

0;i--

)printf

("%c"

,anstr[i]);

return0;

}

習題 最短母串(狀壓)

題目 記憶體限制 512 mib時間限制 1000 ms標準輸入輸出 題目型別 傳統評測方式 文字比較 題目描述 給定n 個字串 要求找到乙個最短的字串 使得這 n個字串都是它 的子串。輸入格式 第一行是乙個正整數 表示給定的字串的個數 以下的 n 1 行,每行有乙個全由大寫字母組成的字串。輸出格式...

HNOI2006 最短母串 狀壓DP

description 給定n個字串 s1,s2,sn 要求找到乙個最短的字串t,使得這n個字串 s1,s2,sn 都是t的子串。sample input 2abcd bcdabc sample output abcdabc 考慮狀壓dp。先去一下重。然後預處理兩個串的最大重疊。然後就是字典序的大小...

洛谷P2622 關燈問題II BFS 狀壓

有m mm個開關和n nn盞燈,第i ii個開關要麼可以開啟第j jj盞燈,要麼可以關上第j jj盞燈,要麼不對第j jj盞燈起作用。求把n nn盞燈全部開啟的最少步數。這道題很明顯可以用bfs bfsbf s做。因為對於每一種情況,我們也就只有m mm種轉移方法,而求的是最優解。而最多只有10盞燈...