在虐各種最長公共子串、子串行的題虐的不耐煩了之後,你決定反其道而行之。
下面給出一些定義:
下面,給兩個小寫字母串 a, ba,b,請你計算:
a 的乙個最短的子串,它不是 b 的子串。
a 的乙個最短的子串,它不是 b 的子串行。
a 的乙個最短的子串行,它不是 b 的子串。
a 的乙個最短的子串行,它不是 b 的子串行。
原本1, 用自動機match寫的, 當匹配失敗的時候取最小值, 然而 a = aabba, b = aabbd, 答案是2, 而不是5
所以要bfs寫, 轉移就完事了, 再sam, sqam上轉移就行, 注意自動機空間是 2n
struct sam tr[n << 1];
int sz, las, len, c[n], rk[n << 1], cnt[n << 1];
int sum[n << 1]; //排名為i的節點為頭包含的字串數量
void init()
void add(int ch)
int q = tr[p].ne[ch];
if (tr[q].len == tr[p].len + 1)
int nq = ++sz; tr[nq] = tr[q]; tr[nq].len = tr[p].len + 1;
for (; p && tr[p].ne[ch] == q; p = tr[p].fa) tr[p].ne[ch] = nq;
tr[q].fa = tr[cur].fa = nq;
}void build(char *s)
} sama, samb;
struct sqam tr[n << 1];
int rt, tot, lst[m];
int newnode()
void init()
void insert(int ch)
void build(char* s)
} a, b;
const int n = 2e3 + 5;
int st[n << 1][n << 1];
char a[n], b[n];
int bfs1() , 0 }); st[1][1] = 1;
while (!q.empty()) , t + 1 });
if (nx && !ny) return t + 1;}}
return -1;
}int bfs2() , 0 }); st[1][1] = 1;
while (!q.empty()) , t + 1 });
if (nx && !ny) return t + 1;}}
return -1;
}int bfs3() , 0 }); st[1][1] = 3;
while (!q.empty()) , t + 1 });
if (nx && !ny) return t + 1;}}
return -1;
}int bfs4() , 0 }); st[1][1] = 4;
while (!q.empty()) , t + 1 });
if (nx && !ny) return t + 1;}}
return -1;
}int main()
HEOI2015 最短不公共子串
字尾自動機 序列自動機 分別建出a,b兩個串的字尾自動機和序列自動機,然後因為字尾自動機和序列自動機都是dag,所以在上面dp一下就可以啦 dp i j 表示在第乙個狀態的自動機上匹配到 i 號節點,在第二個狀態的自動機上匹配到 j 號節點時 還需要新增dp i j 個字元才能使兩串失配 滿足條件 ...
bzoj4032 HEOI2015 最短不公共子串
字尾自動機 序列自動機 序列自動機這東西好像很高階的樣子。其實很簡單的啦。詳細可以看一下我的部落格序列自動機 對字串a構建字尾自動機 str a 和序列自動機 seq a 類似地,對字串b也構建字尾自動機 str b 和序列自動機 seq b 然後對於4個詢問我們分別拿出1個自動機,如第乙個詢問拿出...
HEOI2015 定價 (貪心)
先說一下我對這個題目的態度 首先這一題是貪心,這個十分明顯,看了一眼其他題解都是十分優秀的貪心,可是大家都沒有想過嗎 你們貪心都是在區間 l,r 上列舉的貪心,雖然每一次可以直接加上 10 的階乘,但你們畢竟是用的 int long long 啊!這一題得正解複雜度是 log n 的,不得不說題目的...