用户工具

站点工具


2020-2021:teams:legal_string:jxm2001:字符串_2

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
2020-2021:teams:legal_string:jxm2001:字符串_2 [2020/08/30 11:01]
jxm2001
2020-2021:teams:legal_string:jxm2001:字符串_2 [2020/10/01 20:08] (当前版本)
jxm2001 [算法例题]
行 520: 行 520:
  
 === 例题六 === === 例题六 ===
 +
 +[[https://​ac.nowcoder.com/​acm/​contest/​7817/​G|2020牛客国庆集训派对day1 G题]]
 +
 +== 题意 ==
 +
 +给定 $m$ 个禁止串 $S_i$,求长度为 $n$ 且子串不含任意禁止串的字符串数。
 +
 +数据保证 $\sum_{i=1}^m |S_i|\le 100,n\le 10^9$。
 +
 +== 题解 ==
 +
 +考虑建立 $\text{fail}$ 树,然后标记所有禁止串终止结点以及其在 $\text{fail}$ 树中的子树。
 +
 +然后将树边转化为 $\sum_{i=1}^m |S_i|\times \sum_{i=1}^m |S_i|$ 的邻接矩阵 $A$ 来进行状态转移,套用矩阵快速幂即可快速求解,最后答案即为 $\sum A_{0,i}$。
 +
 +时间复杂度 $O\left((\sum_{i=1}^m |S_i|)^3\log n\right)$。
 +
 +<hidden 查看代码>​
 +<code cpp>
 +const int MAXS=105,​Mod=1e9+7;​
 +struct Matrix{
 + int ele[MAXS][MAXS];​
 + Matrix operator * (const Matrix &b){
 + Matrix c;
 + mem(c.ele,​0);​
 + _for(i,​0,​MAXS)
 + _for(j,​0,​MAXS)
 + _for(k,​0,​MAXS)
 + c.ele[i][j]=(c.ele[i][j]+1LL*ele[i][k]*b.ele[k][j])%Mod;​
 + return c;
 + }
 +};
 +Matrix quick_pow(Matrix a,int n){
 + Matrix ans;
 + mem(ans.ele,​0);​
 + _for(i,​0,​MAXS)
 + ans.ele[i][i]=1;​
 + while(n){
 + if(n&​1)
 + ans=ans*a;​
 + a=a*a;
 + n>>​=1;​
 + }
 + return ans;
 +}
 +namespace AC{
 + int ch[MAXS][26],​val[MAXS],​fail[MAXS],​sz;​
 + void insert(char *s){
 + int len=strlen(s),​pos=0;​
 + _for(i,​0,​len){
 + int c=s[i]-'​a';​
 + if(!ch[pos][c])
 + ch[pos][c]=++sz;​
 + pos=ch[pos][c];​
 + }
 + val[pos]=1;​
 + }
 + int getAns(int n){
 + queue<​int>​q;​
 + _for(i,​0,​26){
 + if(ch[0][i])
 + q.push(ch[0][i]);​
 + }
 + while(!q.empty()){
 + int u=q.front();​q.pop();​
 + _for(i,​0,​26){
 + if(ch[u][i]){
 + fail[ch[u][i]]=ch[fail[u]][i];​
 + val[ch[u][i]]|=val[ch[fail[u]][i]];​
 + q.push(ch[u][i]);​
 + }
 + else
 + ch[u][i]=ch[fail[u]][i];​
 + }
 + }
 + Matrix a;
 + _rep(i,​0,​sz){
 + _rep(j,​0,​sz)
 + a.ele[i][j]=0;​
 + _for(j,​0,​26){
 + if(!val[ch[i][j]])
 + a.ele[i][ch[i][j]]++;​
 + }
 + }
 + a=quick_pow(a,​n);​
 + int ans=0;
 + _rep(i,​0,​sz)
 + ans=(ans+a.ele[0][i])%Mod;​
 + return ans;
 + }
 +}
 +char s[MAXS];
 +int main()
 +{
 + int n=read_int(),​m=read_int();​
 + while(m--){
 + int len=read_int();​
 + scanf("​%s",​s);​
 + AC::​insert(s);​
 + }
 + enter(AC::​getAns(n));​
 + return 0;
 +}
 +</​code>​
 +</​hidden>​
 +
 +=== 例题七 ===
  
 [[https://​www.luogu.com.cn/​problem/​UVA11019|UVA11019]] [[https://​www.luogu.com.cn/​problem/​UVA11019|UVA11019]]
2020-2021/teams/legal_string/jxm2001/字符串_2.1598756461.txt.gz · 最后更改: 2020/08/30 11:01 由 jxm2001