给定n个主串平均长度为len1,m个模式串平均长度为len2,问m个模式串分别在n个字符串中出现了几次?
首先如果用kmp算法,对于n个主串每个主串都和m个模式串进行比较,那么对于每一个主串来说相当于进行了m次kmp所以单个主串需要的时间是mlen1,有n个主串则时间复杂度为O(nmlen1)而接下来介绍的字典树的时间复杂度为O(nlen1+mlen2)
字典树:
(1) 时间复杂度:假设所有字符串长度之和为n
,构建字典树的时间复杂度为O(n)
假设要查找的字符串长度为k
,查找的时间复杂度为O(k)
(2) 空间复杂度:有公共前缀的单词只需要存一次公共前缀,节省了空间
1、维护字符串集合(即字典)。
2、向字符串集合中插入字符串(即建树)。
3、查询字符串集合中是否有某个字符串(即查询)。
4、统计字符串在集合中出现的个数(即统计)。
5、将字符串集合按字典序排序(即字典序排序)。
6、求集合内两个字符串的LCP(Longest Common Prefix,最长公共前缀)(即求最长公共前缀)。
模板: HDU1251
int cnt=0;
int tree[maxn][30];
int num[maxn];//统计前缀出现次数
void insert(string s){
int u=0;
for(int i=0;i
https://ac.nowcoder.com/acm/contest/11222/F
#include
#define int long long
using namespace std;
const int inf=1e9+7;
const int maxn=4e5+5;
struct node{
int l,r;
};
node a[maxn];
int cnt[15]; //分别用来表示1-10时候的cnt
int tree[15][maxn][15];
int val[15][maxn]; //统计长度为1-10时分别的最小答案
vectorb(15);
void insert(vectorv,int vall,int changdu){
//cout<<"insert ";
/*for(int i=1;i<=changdu;i++){
cout<v,int changdu){
int now=0;
for(int i=1;i<=changdu;i++){
if(!tree[changdu][now][v[i]]){
return -1;
}
now=tree[changdu][now][v[i]];
}
return val[changdu][now];
}
signed main(){
for(int i=1;i<=10;i++){
for(int j=0;j<=maxn-1;j++){
val[i][j]=inf;
}
}
for(int i=1;i<=10;i++){
b[i]=i;
insert(b,0,i);
}
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i].l>>a[i].r;
}
for(int i=1;i<=10;i++){
for(int j=1;j<=n;j++){ //枚举右端点
for(int k=1;k<=i;k++){
b[k]=k;
}
for(int k=j;k>=1;k--){ //枚举左端点从k到j交换
int ll=a[k].l,rr=a[k].r;
if(rr>i){
break;
}
//cout<<"len"<>changdu;
for(int i=1;i<=changdu;i++){
cin>>b[i];
}
cout<
https://codeforces.com/contest/1658/problem/D2
#include
using namespace std;
#define int long long
const int mod=998244353;
const int maxn=6e5+5;
int a[maxn];
int tree[maxn][2];
int cnt=0;
void init(){
for(int i=0;i<=cnt;i++){
tree[i][0]=tree[i][1]=0;
}
cnt=0;
}
void insert(int x){
int u=0;
for(int i=32;i>=0;i--){
int now=(x>>i)&1ll;
if(!tree[u][now]){
tree[u][now]=++cnt;
}
u=tree[u][now];
}
}
int find_max(int x){ //找到所有数里面异或x最大的数
int u=0;
int ans=0;
for(int i=32;i>=0;i--){
int now=(x>>i)&1ll;
int want=now^1ll;
if(tree[u][want]){
u=tree[u][want];
ans+=(1ll<=0;i--){
int now=(x>>i)&1ll;
int want=now;
if(tree[u][want]){
u=tree[u][want];
}
else{
ans+=(1ll<>l>>r;
for(int i=l;i<=r;i++){
cin>>a[i];
insert(a[i]);
}
for(int i=l;i<=r;i++){
int x=a[i]^l;
int minn=find_min(x);
int maxx=find_max(x);
if(minn==l&&maxx==r){
cout<>t;
while(t--){
solve();
}
}