FJOI2016Training 公共串问题 【序列自动机+后缀自动机】
1、在 A 的子串中,不是 B的子串的字符串的数量。
2、在 A 的子串中,不是 B的子序列的字符串的数量。
3、在 A 的子序列中,不是 B的子串的字符串的数量。
4、在 A 的子序列中,不是 B的子序列的字符串的数量。
题解:对于 子串,采用 SAM,对于 子序列,采用 SAM。
不要问我为啥都用SAM
因为一个是SeqAM,一个是SufAM。
# include <stdio.h> using namespace std; const int M=4010, Ms=26, Mod=998244353; struct AM { int root, ch[M][Ms], tot, cnt[M]; }; struct SeqAM: public AM { int head[Ms], next[M]; SeqAM() { tot = root = 1; for (int i=0; i<Ms; ++i) head[i] = tot; } inline void insert(char c) { ++tot, next[tot]=head[c]; for (int i=0; i<Ms; ++i) for (int j=head[i]; j && !ch[j][c]; j=next[j]) ch[j][c]=tot; head[c]=tot; } inline void getcnt() { for (int i=1; i<=tot; ++i) cnt[i] = 1; for (int i=tot; i>=1; --i) for (int j=0; j<Ms; ++j) cnt[i] += cnt[ch[i][j]], cnt[i] %= Mod; } }SEA, SEB; struct SufAM: public AM { int fail[M], last, len[M], cl; SufAM() {tot=last=root=1, cl=0;} inline void insert(char c) { ++tot, ++cl; int x=tot, p=last; last=x, len[x] = cl; for (;p && !ch[p][c]; p=fail[p]) ch[p][c] = x; if(!p) fail[x] = root; else if(len[ch[p][c]] == len[p]+1) fail[x] = ch[p][c]; else { int child = ch[p][c], cm = ++tot; len[cm] = len[p]+1; fail[cm] = fail[child]; for (int i=0; i<Ms; ++i) ch[cm][i] = ch[child][i]; fail[child] = fail[x] = cm; for (;ch[p][c] == child; p=fail[p]) ch[p][c] = cm; } } int s1[M], s[M]; inline void getcnt() { for (int i=0; i<M; ++i) s[i]=0; for (int i=1; i<=tot; ++i) s[len[i]]++; for (int i=1; i<M; ++i) s[i]+=s[i-1]; for (int i=1; i<=tot; ++i) s1[s[len[i]]--]=i; for (int i=1; i<=tot; ++i) cnt[i] = 1; for (int i=tot; i>=1; --i) for (int j=0; j<Ms; ++j) cnt[s1[i]] += cnt[ch[s1[i]][j]], cnt[s1[i]] %= Mod; } }SUA, SUB; int dp[M][M]; AM *cura, *curb; int dfs(int a, int b) { if(!a) return 0; if(!b) return cura->cnt[a]; if(dp[a][b] >= 0) return dp[a][b]; int ans=0; for (int i=0; i<Ms; ++i) ans += dfs(cura->ch[a][i],curb->ch[b][i]), ans%=Mod; return dp[a][b] = ans; } int get(AM &a, AM &b) { cura = &a, curb = &b; for (int i=1; i<=a.tot;++i) for (int j=1; j<=b.tot;++j) dp[i][j] = -1; dfs(a.root, b.root); return (dp[a.root][b.root]+Mod)%Mod; } char A[M], B[M]; int main() { scanf("%s%s",A,B); for (int i=0; A[i]; ++i) SEA.insert(A[i]-'a'), SUA.insert(A[i]-'a'); for (int i=0; B[i]; ++i) SEB.insert(B[i]-'a'), SUB.insert(B[i]-'a'); SEA.getcnt(), SEB.getcnt(), SUA.getcnt(), SUB.getcnt(); int AUBU=get(SUA, SUB), AEBE=get(SEA, SEB), AEBU=get(SEA, SUB), AUBE=get(SUA, SEB); printf("%d\n%d\n%d\n%d\n", AUBU, AUBE, AEBU, AEBE); return 0; }
2023年6月18日 15:58
Our reporting team plans to provide the Education & Recruitment Update for all age groups and to present the actual picture of recent events through inside coverage. Our goal is to meet the needs of people of sample-paper.com all ages by publishing news categorised as General, Political, Crime, Sports, Entertainment, Education, and World News.