結果
| 問題 | 
                            No.263 Common Palindromes Extra
                             | 
                    
| コンテスト | |
| ユーザー | 
                             | 
                    
| 提出日時 | 2024-02-18 02:27:23 | 
| 言語 | Go  (1.23.4)  | 
                    
| 結果 | 
                             
                                MLE
                                 
                             
                            
                         | 
                    
| 実行時間 | - | 
| コード長 | 2,793 bytes | 
| コンパイル時間 | 13,908 ms | 
| コンパイル使用メモリ | 231,704 KB | 
| 実行使用メモリ | 248,472 KB | 
| 最終ジャッジ日時 | 2024-09-29 00:01:04 | 
| 合計ジャッジ時間 | 13,812 ms | 
| 
                            ジャッジサーバーID (参考情報)  | 
                        judge2 / judge3 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| other | AC * 11 MLE * 1 | 
ソースコード
package main
import (
	"bufio"
	"fmt"
	"os"
)
func main() {
	yuki263()
}
// No.263 Common Palindromes Extra
// 求两个字符串的公共回文子串的个数 n<=5e5
// https://yukicoder.me/problems/no/263
func yuki263() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var s, t string
	fmt.Fscan(in, &s, &t)
	T := NewPam()
	T.AddString(s + "><" + t)
	dps := make([]int, T.Size())
	dpt := make([]int, T.Size())
	lenS := int32(len(s))
	for i := 0; i < T.Size(); i++ {
		for _, j := range T.Nodes[i].Indexes { // 回文出现位置
			if j < lenS {
				dps[i]++
			} else if j >= lenS+2 {
				dpt[i]++
			}
		}
	}
	res := 0
	for i := T.Size() - 1; i >= 2; i-- { // 按照拓扑序遍历本质不同回文
		res += dps[i] * dpt[i]
		dps[T.Nodes[i].Link] += dps[i]
		dpt[T.Nodes[i].Link] += dpt[i]
	}
	fmt.Fprintln(out, res)
}
type Node struct {
	Next    map[int32]int32 // 子节点.
	Link    int32           // suffix link,指向当前回文串的最长真回文后缀的位置
	Length  int32           // 结点代表的回文串的长度
	Indexes []int32         // 哪些位置的最长回文后缀
}
type Pam struct {
	Ords    []int32
	Nodes   []*Node
	lastPos int32 // 当前字符串(原串前缀)的最长回文后缀
}
func NewPam() *Pam {
	res := &Pam{}
	res.Nodes = append(res.Nodes, res.newNode(0, -1)) // 奇根,长为 -1
	res.Nodes = append(res.Nodes, res.newNode(0, 0))  // 偶根,长为 0
	return res
}
func (pt *Pam) Add(x int32) int {
	pos := int32(len(pt.Ords))
	pt.Ords = append(pt.Ords, x)
	cur := pt.findPrevPalindrome(pt.lastPos)
	_, hasKey := pt.Nodes[cur].Next[x]
	if !hasKey {
		pt.Nodes[cur].Next[x] = int32(len(pt.Nodes))
	}
	pt.lastPos = pt.Nodes[cur].Next[x]
	if !hasKey {
		pt.Nodes = append(pt.Nodes, pt.newNode(-1, pt.Nodes[cur].Length+2))
		if pt.Nodes[len(pt.Nodes)-1].Length == 1 {
			pt.Nodes[len(pt.Nodes)-1].Link = 1
		} else {
			pt.Nodes[len(pt.Nodes)-1].Link = pt.Nodes[pt.findPrevPalindrome(pt.Nodes[cur].Link)].Next[x]
		}
	}
	pt.Nodes[pt.lastPos].Indexes = append(pt.Nodes[pt.lastPos].Indexes, pos)
	return int(pt.lastPos)
}
func (pt *Pam) AddString(s string) {
	if len(s) == 0 {
		return
	}
	for _, v := range s {
		pt.Add(v)
	}
}
func (pt *Pam) Size() int {
	return len(pt.Nodes)
}
func (pt *Pam) GetNode(pos int) *Node {
	return pt.Nodes[pos]
}
func (pt *Pam) newNode(link, length int32) *Node {
	return &Node{
		Next:   make(map[int32]int32),
		Link:   link,
		Length: length,
	}
}
func (pt *Pam) findPrevPalindrome(cur int32) int32 {
	pos := int32(len(pt.Ords) - 1)
	for {
		rev := pos - 1 - pt.Nodes[cur].Length
		// !插入当前字符的条件str[i]==str[i-len-1]
		if rev >= 0 && pt.Ords[rev] == pt.Ords[len(pt.Ords)-1] {
			break
		}
		cur = pt.Nodes[cur].Link
	}
	return cur
}