16.1112 模拟考试 T1
加密
【问题描述】
有一种不讲道理的加密方法是: 在字符串的任意位置随机插入字符。 相应的,
不讲道理的解密方法就是从字符串中恰好删去随机插入的那些字符。
给定原文s和加密后的字符串t,求?有多少子串可以通过解密得到原文s。
【输入格式】
输入第一行包含一个字符串t,第二行包含一个字符串s。
【输出格式】
输出一行,包含一个整数,代表可以通过解密得到原文的s的子串的数量。
【样例输入】
abcabcabc
cba
【样例输出】
9
【样例解释】
用[?,?]表示子串开头结尾的下标(从 0 开始编号) ,这 9 种方案是:
[0,6],[0,7],[0,8],[1,6],[1,7],[1,8],[2,6],[2,7],[2,8]
【数据规模和约定】
30%的数据,|?| 1000。
对于100%的数据,1 ≤ |t| ≤ 300,000,1 ≤ s ≤ 200。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 long long ans; 6 const int N = 301000, M = 210; 7 char S[N], T[M]; 8 int n, m, f[M]; 9 int main() { 10 freopen("encrypt.in", "r", stdin); 11 freopen("encrypt.out", "w", stdout); 12 scanf("%s%s", S + 1, T + 1); 13 n = strlen(S + 1), m = strlen(T + 1); 14 for (int i = 1; i <= n; ++i) { 15 f[0] = i; 16 for (int j = m; j; --j) 17 if (S[i] == T[j]) f[j] = f[j - 1]; 18 ans += f[m]; 19 } 20 printf("%I64d\n", ans); 21 return 0; 22 }
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 typedef long long ll; 7 const int N = (int)3e5 + 10; 8 const int M = 210; 9 char a[N + 1], b[M + 1]; 10 int n, m, p[M + 1]; 11 inline bool move(int x, int l) { 12 for (; l < n && a[l] != b[x]; ++l) ; 13 p[x] = l; 14 return l < n; 15 } 16 inline ll move() { 17 int pos = p[0]; 18 if (!move(0, p[0] + 1)) return 0LL; 19 for (int i = 1; i < m; ++i) 20 if (!move(i, p[i - 1] + 1)) return 0LL; 21 return (ll)(p[0] - pos) * (n - p[m - 1]); 22 } 23 int main(int argc, char *argv[]) { 24 freopen("encrypt.in", "r", stdin); 25 freopen("encrypt.out", "w", stdout); 26 scanf("%s%s", a, b); 27 n = strlen(a), m = strlen(b); 28 ll ans = 0LL, cur; 29 p[0] = -1; 30 while (cur = move()) 31 ans += cur; 32 cout << ans << endl; 33 fclose(stdin); 34 fclose(stdout); 35 return 0; 36 }
思路:我不会,大神求解救~~%%%%%%%%%%%%%%%%%%
付数据~ 提取密码:xvha