给定仅存在小写英文字母的字符串 -1。
首先
不难发现这个
首先有一个思路,已知
然后根据这个思路我们每次转移只需要找到最小的合法 next 数组维护。
具体地,不难发现我们这个东西求的可以转化为求 border,具体地,我们将 P = S + '#' + T,这样我们对 #。
最终 DP 优化为
同时还有一种方法,发现修改状态为后缀可以支持逆序转移,于是转移变为:
此时发现每次可以转移的
xxxxxxxxxx61123
45678910
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 初稿