给定仅存在小写英文字母的字符串 -1
。
首先
不难发现这个
首先有一个思路,已知
然后根据这个思路我们每次转移只需要找到最小的合法 next
数组维护。
具体地,不难发现我们这个东西求的可以转化为求 border,具体地,我们将 P = S + '#' + T
,这样我们对 #
。
最终 DP 优化为
同时还有一种方法,发现修改状态为后缀可以支持逆序转移,于是转移变为:
此时发现每次可以转移的
xxxxxxxxxx
611
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25string S, T;
26char s[1100000];
27int dp[1100000];
28int nxt[1100000];
29
30int main(){
31 memset(dp, 0x3f, sizeof dp);
32 cin >> S >> T;
33 sprintf(s + 1, "%s#%s", S.c_str(), T.c_str());
34 int lenS = S.length(), lenT = T.length();
35 dp[lenS + 1] = 0;
36 int cur(0);
37 for(int i = 2; i <= lenS + lenT + 1; ++i){
38 while(cur && s[cur + 1] != s[i])cur = nxt[cur];
39 if(s[cur + 1] == s[i])++cur;
40 if(i > lenS + 1)dp[i] = dp[i - cur] + 1;
41 nxt[i] = cur;
42 }printf("%d\n", dp[lenS + lenT + 1] < 0x3f3f3f3f ? dp[lenS + lenT + 1] : -1);
43 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
44 return 0;
45}
46
47template < typename T >
48inline T read(void){
49 T ret(0);
50 int flag(1);
51 char c = getchar();
52 while(c != '-' && !isdigit(c))c = getchar();
53 if(c == '-')flag = -1, c = getchar();
54 while(isdigit(c)){
55 ret *= 10;
56 ret += int(c - '0');
57 c = getchar();
58 }
59 ret *= flag;
60 return ret;
61}
update-2022_12_09 初稿