蓝桥杯 算法提高 ADV-288
先来热热身 配合STL
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
typedef pair<string, int> Pair;
const int MAXN = 100 + 1;
vector<Pair> score;
int N;
bool cmp(Pair a, Pair b) {
if (a.second > b.second)
return true;
else if (a.second == b.second&&a.first < b.first)
return true;
else
return false;
}
void pprint(Pair a) {
cout << a.first << " " << a.second << endl;
}
int main() {
string a;
int b;
cin >> N;
while (N--) {
cin >> a >> b;
score.push_back(Pair(a, b));
}
sort(score.begin(), score.end(), cmp);
for_each(score.begin(), score.end(), pprint);
return 0;
}
状态压缩 dp poj 3254 Corn Fields
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 12 + 1;
int field[maxn][maxn];
int r, c;
int state[maxn][maxn];
int dp[maxn][maxn];
bool check(int x, int total) {
if ((x&total) == 0) { //贫瘠的土壤不能种植
if ((x&(x << 1)) == 0)
return true;
}
return false;
}
int main() {
memset(field, 0, sizeof(field));
memset(state, 0, sizeof(state));
memset(dp, 0, sizeof(dp));
cin >> r >> c;
for (int i = 0; i < r; i++) {
int total = 0; //用来判断贫瘠的土壤不能种
for (int j = 0; j < c; j++) {
cin >> field[i][j];
total = total << 1;
if(field[i][j]==0)
total += 1;
}
int k = 1;
for (int e = 0; e < (1 << c); e++) {
if (check(e, total)) {
state[i][k] = e;
k++;
}
}
state[i][0] = k - 1; //记录这一行有几种可行方案
}
for (int i = 1; i <= state[0][0]; i++)
dp[0][i] = 1;
for (int i = 1; i < r; i++) { //从第二行开始遍历
for (int j = 1; j <= state[i][0]; j++) { //从第二行的各个元素遍历
for (int k = 1; k <= state[i - 1][0]; k++) { //遍历前一行所有元素
if ((state[i][j] & state[i - 1][k]) == 0)
dp[i][j] += dp[i - 1][k];
}
}
}
int ans=0;
for (int i = 1; i <= state[r - 1][0]; i++)
ans += dp[r - 1][i];
cout << ans << endl;
return 0;
}
模式匹配 求子串
kmp算法
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1000+5;
char str[MAXN],pattern[MAXN];
int Next[MAXN];
int cnt;
int getFail(char *p,int plen){
//预计算Next[],用于在失配的情况下得到j回溯的位置
Next[0]=0;Next[1]=0;
for(int i=1;i<plen;i++){
int j=Next[i];
while(j&&p[i]!=p[j])
j=Next[j];
Next[i+1]=(p[i]==p[j])?j+1:0;
}
}
int kmp(char *s,char *p){ //在S中找P
int last=-1;
int slen=strlen(s),plen=strlen(p);
getFail(p,plen); //预计算Next[]数组
int j=0;
for(int i=0;i<slen;i++){ //匹配S和P的每个字符
while(j&&s[i]!=p[j]) //失配了,用Next[]找j的回溯位置
j=Next[j];
if(s[i]==p[j]) //当前位置字符匹配,j++
j++;
if(j==plen){
if(i-last>=plen){ //判断这次匹配和上个匹配能否分开
cnt++;
last=i; //last指向上一次匹配的末尾
}
}
}
}
int main(){
while(~scanf("%s",str)){ //读串
if(str[0]=='#')
break;
scanf("%s",pattern); //读字符串
cnt=0;
kmp(str,pattern);
printf("%d\n",cnt);
}
return 0;
}
//暴力算法
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=1000;
char S[MAXN];
char P[MAXN];
int slen,plen;
int cnt=0;
int main(){
cin>>S>>P;
slen=strlen(S);
plen=strlen(P);
int j=0;
for(int i=0;i<slen;i++){
if(S[i]==P[j])
j++;
else{
j=0;
i=i-j;
}
if(j==plen){
j=0;
cnt++;
}
}
cout<<cnt<<endl;
return 0;
}
还有一种sunday算法,较kmp而言容易理解,时间复杂度平均为O(n),代码如下
//sunday算法
#include <iostream>
#include <string>
using namespace std;
const int maxNum = 1005;
int shift[maxNum];
void Sunday(const string& T, const string& P) {
int n = T.length();
int m = P.length();
// 默认值,移动m+1位
for(int i = 0; i < maxNum; i++) {
shift[i] = m + 1;
}
// 模式串P中每个字母出现的最后的下标
// 所对应的主串参与匹配的最末位字符的下一位字符移动到该位,所需要的移动位数
for(int i = 0; i < m; i++) {
shift[P[i]] = m - i; //P[i]为字符,int为其ASCII,看成映射
}
// 模式串开始位置在主串的哪里
int s = 0;
// 模式串已经匹配到的位置
int j;
while(s <= n - m) {
j = 0;
while(T[s + j] == P[j]&&j<m) {
j++;
// 匹配成功
if(j >= m) {
cout << "模式串在主串的位置为:" << s << endl;
}
}
// 找到主串中当前跟模式串匹配的最末字符的下一个字符
// 在模式串中出现最后的位置
// 所需要从(模式串末尾+1)移动到该位置的步数
s += shift[T[s + m]];
}
}
int main() {
// 主串和模式串
string T, P;
while(true) {
// 获取一行
getline(cin, T);
getline(cin, P);
Sunday(T, P);
}
return 0;
}
代码来自https://blog.csdn.net/q547550831/article/details/51860017