2024.12.21
wangzilong913 · · 个人记录
重生之我与字符串的殊死搏斗
wangzilong913: 该死的字符串,纳命来!!
string: 就凭你?吃我一招最小表示法橫劈!!
一.最小表示法
1.基本概念:
给定一个字符串,如果我们不断把它的最后一个字符放到开头,最终得到
(字典序:在比较字典序中,首先比较两个字符串的第一个字符,如果不同,则第一个字符较小的字符串更小;如果相同,则继续比较下一个字符,依此类推,直到比较完所有字符。如果一个字符串是另一个字符串的前缀,则较短的字符串更小。)
2.基本原理:
首先把
如果在
同理,如果
因此,我们可以做到用
3.模板:
P1368 【模板】最小表示法
注:原题是整数的最小表示,此处写的是字符串
#include <bits/stdc++.h>
using namespace std;
int n,ans;
char a[6000010];
int main(){
ios::sync_with_stdio(0);
cin>>n;
for(int i = 1;i <= n;i++){
cin>>a[i];
a[i+n] = a[i];
}
int i = 1,j = 2,k;
while(i <= n && j <= n){
for(k = 0;k < n && a[i+k] == a[j+k];k++);
if(k == n) break;
if(a[i+k] > a[j+k]){
i = i + k + 1;
if(i == j) i++;
}
else{
j = j + k + 1;
if(i == j) j++;
}
}
ans = min(i,j);
for(int i = ans;i < ans+n;i++){
cout<<a[i]<<" ";
}
return 0;
}
string: 居然抗住了这一刀,看来是小瞧你了。
wangzilong: 代码量又小,理解也不难,你看这string就是逊啊!!
string: 哟,这么说你很勇咯。区区蝼蚁,也妄想挑战我。看我这招Trie树诛仙锁!!
二.Trie树
1.基本概念:
Trie树,又叫字典树、前缀树(Prefix Tree)、单词查找树 或 键树,是一种多叉树结构。
Trie树的基本性质:
-
根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
-
从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
-
每个节点的所有子节点包含的字符互不相同。
2.实现
插入:
当需要插入一个字符串
- 若
P 的c 字符指向一个已经存在的节点Q ,则令P=Q 。 - 若
P 的c 字符指向空,则新建一个节点Q ,令P 的c 字符指针指向Q ,然后令P=Q 。
当
检索:
当需要检索一个字符串
- 若
P 的c 字符指向空,则说明S 没有被插入过Trie树,结束检索。 - 若
P 的c 字符指向一个已经存在的节点Q ,则令P=Q 。
当
3.模板:
P10470 前缀统计
#include <bits/stdc++.h>
using namespace std;
int n,m;
int t[1000005][26];
int cnt[1000005];
int now;
void cha(string s){
int p=0;
for(int i = 0;i < (int)s.size();i++){
if(t[p][s[i]-'a'] == 0){
t[p][s[i]-'a'] = ++ now;
}
p = t[p][s[i]-'a'];
}
cnt[p]++;
}
int zhao(string s){
int p=0,m=0;
for(int i = 0;i < (int)s.size();i++){
if(t[p][s[i]-'a'] == 0){
return m;
}
p = t[p][s[i]-'a'];
m+=cnt[p];
}
return m;
}
int main(){
cin>>n>>m;
while(n--){
string s;
cin>>s;
cha(s);
}
while(m--){
string s;
cin>>s;
cout<<zhao(s)<<endl;
}
return 0;
}