本专栏主要为了巩固基础算法,会把比赛中觉得比较好的题目拿过来整理一下。
今天整理昨天落下的F题(其实是补一下KMP算法),以及牛客周赛的D题。
一、P3375 【模板】KMP - 洛谷
题目来源:洛谷
题目难度:★★
下面是有关kmp的相关知识:
模板代码:
#include <iostream>
#include <vector>
using namespace std;
const int N = 1e6 + 10;
int ne[N];
string s1, s2;
void get_next()
{
int m = s2.size();
ne[0] = -1; ne[1] = 0;
int i = 2, cn = 0;
while(i <= m)
{
if(s2[i - 1] == s2[cn])
{
ne[i++] = ++cn;
}
else if(cn > 0)
{
cn = ne[cn];
}
else
{
ne[i++] = 0;
}
}
}
vector<int> kmp()
{
vector<int> ret;
int n = s1.size(), m = s2.size();
int x = 0, y = 0;
while(x < n)
{
if(s1[x] == s2[y])
{
x++; y++;
}
else if(y == 0)
{
x++;
}
else
{
y = ne[y];
}
if(y == m)
{
ret.push_back(x - y + 1);
// y = 0; x = x - y + 1;
}
}
return ret;
}
int main()
{
cin >> s1 >> s2;
get_next();
vector<int> ans = kmp();
for(auto x : ans) cout << x << endl;
for(int i = 1; i <= s2.size(); i++) cout << ne[i] << " ";
return 0;
}
二、D-小苯的数字集合_牛客周赛 Round 86
题目来源:牛客网
题目难度:★★
【解题】:首先要明确本题的最大次数是3,这点很重要,因为明白了这一点之后我们就可以直接列出1 ,2次的情况,否则输出三。
对于两个满足要求的数x,y,如果两个数在进行了1,2次任意上述运算之后没有出现零,那么前两次我完全可以只用一种运算构造出一个相同的数,然后xor直接是零。
所以我们只需要列出次数为1的情况:(x & y) (x ^ y) (gcd(x, y)这四种里面有零就是1次。
2次的情况:a = (x & y) b = (x ^ y) c = (gcd(x, y),然后这三个数对x,y再次进行上述三种运算(不用考虑 or 操作)只要有零就可以输出2。
🖥️code:
#include <iostream>
using namespace std;
int T;
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
bool check(int a, int x, int y)
{
return !(a & x) || !(a & y)
||!(a ^ x) || !(a ^ y)
||!(gcd(a, y)) || !(gcd(a, x));
}
int main()
{
cin >> T;
while(T--)
{
int x, y; cin >> x >> y;
if(!(x & y) || !(x ^ y) || !(gcd(x, y)))
{
cout << 1 << endl;
}
else
{
int a = x & y;
int b = x ^ y;
int c = gcd(x, y);
if(check(a, x, y) || check(b, x, y) || check(c, x, y))
{
cout << 2 << endl;
}
else
{
cout << 3 << endl;
}
}
}
return 0;
}