[Usaco10Dec] Threatening Letter G - 后缀自动机,贪心
Posted mollnn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Usaco10Dec] Threatening Letter G - 后缀自动机,贪心相关的知识,希望对你有一定的参考价值。
Description
给你一个长度为 (n) 的串 (s_1),再给你一个长度为 (m) 的串 (s_2),问需要至少多少个 (s_1) 的子串才可以拼成 (s_2)?
Solution
对 (s_1) 建出 SAM,把 (s_2) 放到上面贪心地跑,如果能匹配就接着沿着 (trans) 边走,不匹配则回到根结点,并且 (ans+1)
#include <bits/stdc++.h>
using namespace std;
const int N = 2000005;
int ans=1;
struct SAM {
int len[N], ch[N][26], fa[N], ind, last;
int t[N], a[N], cnt[N], f[N];
SAM() { ind = last = 1; }
inline void extend(int id) {
int cur = (++ ind), p;
len[cur] = len[last] + 1;
cnt[cur] = 1;
for (p = last; p && !ch[p][id]; p = fa[p]) ch[p][id] = cur;
if (!p) fa[cur] = 1;
else {
int q = ch[p][id];
if (len[q] == len[p] + 1) fa[cur] = q;
else {
int tmp = (++ ind);
len[tmp] = len[p] + 1;
for(int i=0;i<26;i++) ch[tmp][i] = ch[q][i];
fa[tmp] = fa[q];
for (; p && ch[p][id] == q; p = fa[p]) ch[p][id] = tmp;
fa[cur] = fa[q] = tmp;
}
}
last = cur;
}
int p=1;
void go(int id)
{
if(ch[p][id]) p=ch[p][id];
else p=ch[1][id], ++ans;
}
} sam;
int main() {
ios::sync_with_stdio(false);
string str,tmp;
int n,m;
cin>>n>>m;
while(str.length()<n)
{
cin>>tmp;
str+=tmp;
}
for(int i=0;i<n;i++) sam.extend(str[i]-‘A‘);
str="";
while(str.length()<m)
{
cin>>tmp;
str+=tmp;
}
for(int i=0;i<m;i++) sam.go(str[i]-‘A‘);
cout<<ans<<endl;
}
以上是关于[Usaco10Dec] Threatening Letter G - 后缀自动机,贪心的主要内容,如果未能解决你的问题,请参考以下文章
洛谷 P3004 [USACO10DEC]宝箱Treasure Chest
洛谷P3004 [USACO10DEC]宝箱Treasure Chest
洛谷P3003 [USACO10DEC]苹果交货Apple Delivery
洛谷 P3003 [USACO10DEC]苹果交货Apple Delivery