zoukankan      html  css  js  c++  java
  • 『妙不可言系列2』CF1336C Kaavi and Magic Spell

    (mathrm{Problem})

    Kaavi, the mysterious fortune teller, deeply believes that one's fate is inevitable and unavoidable. Of course, she makes her living by predicting others' future. While doing divination, Kaavi believes that magic spells can provide great power for her to see the future.

    Kaavi has a string $ T $ of length $ m $ and all the strings with the prefix $ T $ are magic spells. Kaavi also has a string $ S $ of length $ n $ and an empty string $ A $ .

    During the divination, Kaavi needs to perform a sequence of operations. There are two different operations:

    • Delete the first character of (S) and add it at the front of (A) .
    • Delete the first character of (S) and add it at the back of (A) .

    Kaavi can perform no more than (n) operations. To finish the divination, she wants to know the number of different operation sequences to make (A) a magic spell (i.e. with the prefix (T) ). As her assistant, can you help her? The answer might be huge, so Kaavi only needs to know the answer modulo (998\,244\,353) .

    Two operation sequences are considered different if they are different in length or there exists an (i) that their (i) -th operation is different.

    A substring is a contiguous sequence of characters within a string. A prefix of a string (S) is a substring of (S) that occurs at the beginning of (S) .

    给定一个字符串 (S) 和一个字符串 (T),每次可以删掉 (S) 的第一个字符,然后放到一个初始为空的字符串 (A) 的首部或尾部,求有多少种不同的方法使得最后 (T)(A) 的前缀。

    (mathrm{Solution})

    这道题的特性在于,A串的特性是两边拓展的。我们可以从A串这个与众不同的特点来思考问题。

    • 对于不断两边拓展的问题需要想到区间DP

    这一点是解题的关键。但是这道题要求这个串满足T是该串的前缀,那我们可以在状态上做手脚。

    • (f[l][r])表示用((r-l+1))个S字符前后拼接形成A串,A串的区间([mathrm L, ext R])内的任意一个字符符合条件的方案数。这里字符i符合条件当且仅当满足(i>|T|)或者(ile |T|且A_i=T_i).

    那样我们就可以考虑使用区间DP的方式去进去转移了。

    我们考虑方程的转移,对于一个(l)(r)和区间的长度( ext{len=r-l+1}.)

    • 对于s[len]=t[i]或者i>m的情况,说明当前新加入的字母足以匹配可以成为开头或开头可以选择任意字母,那么就有:(f[i][j]+=f[i+1][j])
    • 对于s[len]=t[j]或者j>m的情况,同理:(f[i][j]+=f[i][j-1])

    (mathrm{Code})

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 4000;
    const int P = 998244353;
    
    int n, m;
    int f[N][N];
    char S[N], T[N];
    
    int main(void)
    {
    	cin >> S+1 >> T+1;
    	n = strlen(S+1);
    	m = strlen(T+1);
    	for (int i=1;i<=n;++i)
    		f[i][i] = (i > m || S[1] == T[i])*2;
    	for (int len=2;len<=n;++len)
    		for (int i=1;i+len-1<=n;++i) {
    			int j = i + len - 1;
    			if (S[len] == T[i] || i > m) f[i][j] = (f[i][j] + f[i+1][j]) % P;
    			if (S[len] == T[j] || j > m) f[i][j] = (f[i][j] + f[i][j-1]) % P;
    		} 	
    	int res = 0;
    	for (int i=m;i<=n;++i)
    		res = (res + f[1][i]) % P;
    	cout << res << endl;
    	return 0;
    } 
    
  • 相关阅读:
    循环队列
    UVa10000_Longest Paths(最短路SPFA)
    最新jhost免费jsp云空间会员邀请码
    Vertica: 基于DBMS架构的列存储数据仓库
    java中接口的定义与实现
    【C++知识汇总】运营商 &amp; 运算符重载
    SVN与eclipse整合和利用、SVN与Apache综合
    Java单链逆转
    hdu1115(重力算法的多边形中心)
    高效C++规划
  • 原文地址:https://www.cnblogs.com/pigzhouyb/p/12755540.html
Copyright © 2011-2022 走看看