文章目录
蓝桥杯备赛题目记录
字符串专题
1、Manacher算法
(1)回文串
※ 回文递归性质:
(2)算法内容
(3)例题:最长回文子串
1225.最长回文子串
代码:
#include <iostream>
#include <cstring> // 计算字符串str长度时,strlen()会用到
using namespace std;
const int N = 1e6 + 9;
char str[N]; // 字符串
int dp[N]; // 回文半径
int main()
{
cin >> str + 1; // 从str[1]开始输入
int n = strlen(str + 1); // 相应地计算str的长度
for(int i = 2 * n + 1; i >= 1; i --)
{
if(i & 1) str[i] = '#'; // 奇数位为字符‘#’
else str[i] = str[i >> 1]; // 偶数位为原字符
}
str[0] = '^', str[2 * n + 2] = '$'; // 二者都是用来占位的,什么符号都无所谓
int c = 0, r = 0; // c是当前回文子串的中心(关于r),r是当前回文子串的右边界
for(int i = 1; i <= 2 * n + 1; i ++)
{
// 如果当前符号所处位置没有超过回文子串右边界
if(i < r) dp[i] = min(r - i, dp[2 * c - i]); // 由回文递归性质可得
else dp[i] = 1; // 否则回文半径为1,因为该回文子串中只含有当前字符
while(str[i - dp[i]] == str[i + dp[i]]) dp[i] ++; // 以当前字符向两边同步扩展遍历,两边字符相同就是回文
if(i + dp[i] > r) c = i, r = i + dp[i]; // 如果当前字符所在位置已经超过回文子串右边界,则更新回文子串
}
int ans = 0;
for(int i = 1; i <= 2 * n + 1; i ++) ans = max(ans, dp[i] - 1);
// (pi + pi -1) / 2 下取整,结果为 pi - 1
cout << ans << endl;
return 0;
}
2、KMP算法
(1)定义
(2)算法内容
}
(3)例题:斤斤计较的小Z
2047.斤斤计较的小Z
代码:
#include <iostream>
#include <vector>
using namespace std;
void cal_nex(string str2, vector<int>& nex)
{
nex.resize(str2.length() + 1);
nex[0] = -1;
int k = -1, j = 0;
int len2 = str2.length();
while(j < len2 - 1)
{
if(k == -1 || str2[k] == str2[j])
{
k ++, j ++;
nex[j] = k;
}
else k = nex[k];
}
}
int kmp(string str1, string str2, vector<int>& nex)
{
int ans = 0;
cal_nex(str2, nex);
int k = 0, j = 0;
int len1 = str1.length(), len2 = str2.length();
while(j < len1)
{
if(k == -1 || str1[j] == str2[k]) k ++, j ++;
else k = nex[k];
if(k == len2)
{
ans ++;
k = nex[k];
}
}
return ans;
}
int main()
{
string str1, str2;
cin >> str1 >> str2;
vector<int> nex;
cout << kmp(str2, str1, nex) << endl;
return 0;
}
3、字符串哈希
(1)定义
(2)例题:斤斤计较的小Z(同上)
代码:
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1e6 + 5, P = 131;
typedef unsigned long long ULL;
char a[N], b[N];
ULL h1[N], h2[N], p[N];
void my_hash(ULL ha[], int n, char str[])
{
p[0] = 1;
for (int i = 1; i <= n; i ++)
{
p[i] = p[i - 1] * P;
ha[i] = ha[i - 1] * P + str[i];
}
}
ULL get(int l, int r)
{
return h1[r] - h1[l - 1] * p[r - l + 1];
}
int main()
{
int aLen, bLen;
cin >> b + 1 >> a + 1;
aLen = strlen(a + 1), bLen = strlen(b + 1);
my_hash(h1, aLen, a);
my_hash(h2, bLen, b);
int res = 0;
for (int i = 1; i + bLen - 1 <= aLen; i ++ )
{
int j = i + bLen - 1;
if (get(i, j) == h2[bLen]) res ++;
}
cout << res;
return 0;
}