题解 P1819 【公共子序列】
在窝的博客食用更佳
大家好,本蒟蒻又来写题解了。本题解可以看做对 @神之右大臣 巨佬的题解的补充。(注:本文部分内容引用自此文)
这次这道题目所使用的算法是序列自动机,其最直接的作用是查找某个字符串是否是另一个字符串的子序列。下面给大家普及一下。
首先要清楚的是,序列自动机完全不像 AC 自动机,后缀自动机 那样高大上,本质上就是一个牺牲空间换时间的字符串记忆。百度百科甚至都没有这个词条
我们定义
string s="abcdefg",s2=s.substr(i,c.end-c-i);
nxt[i][j]=s2.find(j+'a')+i;
那么我们的预处理就很清晰了,倒着遍历更新即可:
const int inf=0x3f3f3f3f;
int nxt[N][27];
void init(char *s) {
int l=strlen(s);
for(int i=0;i<26;i++) nxt[l][i]=inf;
for(int i=l-1;i>=0;i++) { //倒着枚举起点
for(int j=0;j<26;j++) //枚举字母
nxt[i][j]=nxt[i+1][j];
nxt[i][s[i]-'a']=i //更新当前位置的nxt
}
}
查询时,我们令指针 false:
bool find(char *t) {
int p=-1,l=strlen(t);
for(int i=0;i<l;i++) {
p=nxt[p+1][t[i]-'a'];
if(p==inf) return false;
}
return true;
}
那么在这道题里怎么办呢?答案是记忆化搜索。
我们令 dfs 即可。也就是说,如果字母为 nxta[x][i]&nxtb[y][i]&nxtc[z][i] 那么就可以 dfs。最后,只要当前
最后提醒大家,千万别忘了取模!
完结撒花~
看我写的这么详细,不点个赞再走嘛?~