在構造它之前,我們必須先證明一個長度n的字串其不同的回文子字串個數<=n,什麼是不同的回文子字串?就是長的不同的回文子字串,及把出現位置不同但形狀一樣的回文子字串當做是同樣的子字串。
證明:
- 由左往右一個一個增加字符,則新產生的回文子字串其結尾一定是當前增加的字符x
- 考慮以當前位置為結尾的最長回文x......x,顯而易見的,若產生除了x......x之外其它的回文子串,則必定被x......x所包含
- 若增加字符x後,產生了除了x......x之外其它的回文子串,則根據回文的性質,其一定早已在x......的部分理出現(例:假設S是對稱點x...S.xax,因為回文的性質所以S的另一邊也會出現相同的字串xax.S.xax)
- 因此每增加一個字符最多只會產生一個新的回文子字串,而長度為n的字符串最多只會產生n種不同的回文子字串
回文自動機包含以下元素:
- 狀態St,所有節點的集合,一開始兩個節點,0表示偶數長度串的根和1表示奇數長度串的根
- last 新增加一個字符後所形成的最長回文串的節點編號
- s 當前的字符串(一開始設s[0]=-1(可以是任意一個在串S中不會出現的字符))
- n 表示添加的字符個數
每個節點代表一個不同的回文子字串,我們在每個節點會儲存一些數值:
- len 表示所代表的回文子字串長度
- next[c] 表示所代表的回文子字串在頭尾各增加一個字符c後的回文字串其節點編號
- fail 表示所代表的回文子字串不包括本身的最長後綴回文子串的節點編號
- cnt(非必要) 表示所代表的回文子字串在整體字串出現的次數(在建構完成後呼叫count()才能計算)
- num(非必要) 表示所代表的回文子字串其後綴為回文字串的個數
關於構造方法及圖片說明請參考:http://blog.csdn.net/u013368721/article/details/42100363
概念請參考:http://blog.csdn.net/MaticsL/article/details/43651169
證明請參考:http://yqcmmd.com/index.php/2015/03/30/746/
最後提供模板(使用STL vector),因為St的元素在解題的過程中常會被用到所以就不封裝了:
沒有留言:
張貼留言