本文最后更新于 2025年3月9日 中午
P3375 【模板】KMP
https://www.luogu.com.cn/problem/P3375
题解
kmp算法模板,输出匹配开始位置,最后再输出next数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include<bits/stdc++.h> using namespace std;
const int N=1000010; string s,p; int ne[N];
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); s=" ",p=" "; string s1,p1; cin>>s1>>p1; s+=s1,p+=p1; int lens=s.length()-1; int lenp=p.length()-1; for(int i=2,j=0;i<=lenp;i++) { while(j&&p[i]!=p[j+1]) j=ne[j]; if(p[j+1]==p[i]) j++; ne[i]=j; }
for(int i=1,j=0;i<=lens;i++) { while(j&&s[i]!=p[j+1]) j=ne[j]; if(s[i]==p[j+1]) j++; if(j==lenp) { cout<<i-lenp+1<<'\n'; j=ne[j]; } } for(int i=1;i<=lenp;i++) cout<<ne[i]<<' '; return 0; }
|
P1507 NASA的食物计划
https://www.luogu.com.cn/problem/P1507
题解
01背包的变形,限制条件变成了两个:体积、质量。
只需开个二维dp[i][j]数组,第一个下标代表体积,第二个下标代表质量。表示体积最大为i的情况下,重量最大为j时的最大价值
状态转移方程:dp[j][l] = max(dp[j][l], dp[j - h1[i]][l - t1[i]] + k[i])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include<bits/stdc++.h> using namespace std;
const int N = 405,M=51; int h, t; int n; int h1[M], t1[M], k[M]; int dp[N][N];
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
cin >> h >> t; cin >> n; for (int i = 1; i <= n; i++) { cin >> h1[i] >> t1[i] >> k[i]; for (int j = h; j >= h1[i]; j--) { for (int l = t; l >= t1[i]; l--) { dp[j][l] = max(dp[j][l], dp[j - h1[i]][l - t1[i]] + k[i]); } } } cout << dp[h][t];
return 0; }
|
P1470 最长前缀 Longest Prefix
https://www.luogu.com.cn/problem/P1470
题解
dp问题。dp[i]表示从1到i的前缀字符串是否可以用p拼接.
状态转移:if(h.count(t)&&dp[i-j]) dp[i]=true; 如果从1到i-j可以表示,且i-j到i在p中存在,那么dp[i]也可以表示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include<bits/stdc++.h>
using namespace std;
const int N = 200010; int max1 = 0; string s, x; unordered_set<string> h; int dp[N];
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
while (cin >> s, s != ".") { h.insert(s); max1 = max(max1, (int)s.size()); } s = " "; while (cin >> x) s += x; dp[0] = true; int ans = 0; for (int i = 1; i < s.size(); i++) { for (int j = min(max1, i); j >= 1; j--) { string t = s.substr(i - j + 1, j); if (h.count(t) && dp[i - j]) { dp[i] = true; ans = i; break; } } } cout << ans;
return 0; }
|