A 子串查找
哈希加密函数:hash[i]=hash[i−1]∗p+idx(s[i])(idx指的是待加密字符串,p是质数)
哈希加密函数(带取余):hash[i]=(hash[i−1])∗p+idx(s[i]) % mod(p和mod都是质数)
查询某段的哈希值:hash=hash[r]−hash[l−1]∗p^(r−l+1) (因为哈希加密时会多次乘p,要在区间左端点乘上相应“长度”大小的p幂次来平衡式子)。
本题是哈希模板题。
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include<queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll nextlong()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
char a[5000000], b[5000000];
ull hashes[5000000],password[5000000];
void init(ll n)
{
hashes[1] = 37;
for (int i = 2; i <= n+3; i++)
hashes[i] = hashes[i - 1] * 37;
}
ull encry(ll len)
{
ll ans = 0;
for (int i = 1; i <= len; i++)
ans = ans * 37 + (b[i]);
return ans;
}
void encry2(ll len)
{
for (int i = 1; i <= len; i++)
password[i] = (password[i-1] * 37)+ a[i];
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> (a+1) >> (b+1);
ll len1 = strlen(a + 1);
ll len2 = strlen(b + 1);
init(max(len1, len2));
ull encryed = encry(len2);
encry2(len1);
ll cnt = 0;
//cout << encryed << endl;
for (int i = len2; i <= len1; i++)
{
//cout << password[i] - password[i - len2] * hashes[len2] << endl;
if (encryed ==(password[i] - password[i - len2]*hashes[len2]))//取值函数
cnt++;
}
cout << cnt << endl;
return 0;
}
B
本题需要你设计一个重复率较低的哈希函数,一般P和mod取大质数即可。
map模组亦可解决。
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include<queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll nextlong()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
set<ull>st;
ull encry(string tmp)
{
ll ans = 0;
for (int i = 0; i < tmp.size(); i++)
ans = (ans * 37) + tmp[i];
return ans;
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
ll n;
cin >> n;
string cmd,name;
for (int i = 1; i <= n; i++)
{
cin >> cmd;
getline(cin,name);
if (cmd == "add")
st.insert(encry(name));
else
{
if (st.find(encry(name)) != st.end())
cout << "yes" << endl;
else
cout << "no" << endl;
}
}
return 0;
}
C power string
找到字符串的最小正周期即可,但是枚举周期会超时。这里使用了KMP算法中的NEXT数组作为辅助
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include<queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll nextlong()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
char tmp[5000000];
ll nxt[5000000];
void getnext()
{
ll ph = 0,pt = -1;
nxt[0] = -1;
ll len = strlen(tmp);
while (ph<len)
{
if (pt == -1 || tmp[ph] == tmp[pt])
nxt[++ph] = ++pt;
else
pt = nxt[pt];
}
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
while (cin >> tmp)
{
if (tmp[0] == '.')
break;
reset(nxt, 0);
getnext();
ll total = strlen(tmp);
ll len2 = total / (total - nxt[total]);//总长度除以最小正周期
cout << len2 << endl;
}
return 0;
}
K
KMP和哈希都可做。
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include<queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll nextlong()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
string text,sub;
ll nexxt[500000];
void getnext()
{
ll pt = 0, pt2 = -1;
nexxt[0] = -1;
while (pt < sub.size())
{
if (pt2 == -1 || sub[pt2] == sub[pt])
{
nexxt[++pt] = ++pt2;
}
else
pt2 = nexxt[pt2];
}
}
ll cnt = 0;
void kmp()
{
getnext();
ll pt1 = 0, pt2 = 0;
while (pt1 < text.size())
{
//cout << pt1 << " " << pt2 << endl;
if (pt2 == -1 || sub[pt2] == text[pt1])
pt2++, pt1++;
else
pt2 = nexxt[pt2];
if (pt2 == sub.size())
{
cnt++;
pt2 = 0;
}
}
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
while (cin >> text)
{
if (text == "#")
break;
cin >> sub;
reset(nexxt, 0);
cnt = 0;
kmp();
cout << cnt << endl;
}
return 0;
}
X 玄武密码
AC自动机模板题,不过需要在母串查询时对所经节点打标记。
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include<queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll nextlong()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
char text[10000089], tmp[170001][2500];
int trie[10000071][5], fail[10000071], length[10000071];
int bottom[10000071];
bool vis[10000071];
ll cnt = 0;
ll cal(char x)//由于只有四个字母,只需要做一个四叉字典树即可。
{
if (x == 'E')
return 1;
else if (x == 'N')
return 2;
else if (x == 'S')
return 3;
else if (x == 'W')
return 4;
}
void ins(ll index,char *tmp)
{
ll rt = 0;
vis[0] = 1;
for (int i = 0; tmp[i]; i++)
{
ll t = cal(tmp[i]);
if (trie[rt][t] == 0)
trie[rt][t] = ++cnt;
rt = trie[rt][t];
}
}
void getfail()
{
queue<ll>q;
for (int i = 1; i <= 4; i++)
{
if (trie[0][i])
{
fail[trie[0][i]] = 0;
q.push(trie[0][i]);
}
}
while (!q.empty())
{
ll current = q.front();
q.pop();
for (int i = 1; i <= 4; i++)
{
if (trie[current][i])
{
fail[trie[current][i]] = trie[fail[current]][i];
q.push(trie[current][i]);
}
else
trie[current][i] = trie[fail[current]][i];
}
}
}
void mark(char *t)
{
ll current = 0;
for (int i = 0; t[i]; i++)
{
current = trie[current][cal(t[i])];
for (int j = current; j != 0; j = fail[j])//对fail指针经过的节点打标记
{
if (vis[j])
break;
else
vis[j] = 1;
}
}
}
ll query(char *st)
{
ll current = 0, ans = 0;
for (int i = 0; st[i]; i++)
{
ll t = cal(st[i]);
current = trie[current][t];
if (vis[current])//找标记即可
ans ++;
}
return ans;
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
ll n, m;
cin >> n >> m;
cin >> text;
for (int i = 1; i <= m; i++)
{
cin >> tmp[i];
length[i] = strlen(tmp[i]);
ins(i,tmp[i]);
}
getfail();
mark(text);
for (int i = 1; i <= m; i++)
cout << query(tmp[i]) << endl;
return 0;
}