Loading

笔记-两道类似的 Z 函数习题

真是很神奇的东西,感觉有些题可以吊打 SAM 啊。


CF432D Prefixes and Suffixes

CF432D Prefixes and Suffixes


先对整个字符串搞一次 Z

如果 \(i+ze(i)=n\) 说明这是原串的一个 border 后缀,将 \(ze(i)\) 标为可能长度。

对每个 \(ze(i)\)\(cnt(ze(i))++\),然后后缀和一下就好了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int N=1e5;
int n,cnt[N|1];
bool mat[N|1];
string str;

//Zebra
int ze[N];
void ze_init(){
    int l=0;
    R(i,n)if(i){
        if(l+ze[l]>i) ze[i]=min(l+ze[l]-i,ze[i-l]);
        while(i+ze[i]<n&&str[ze[i]]==str[i+ze[i]]) ze[i]++;
        if(i+ze[i]>l+ze[l]) l=i;
    }
}

//Main
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>str,n=sz(str),ze_init();
    // R(i,n) cout<<ze[i]<<' '; cout<<'\n';
    R(i,n)if(i){
        if(i+ze[i]==n) mat[ze[i]]=true;
        cnt[ze[i]]++;
    }
    mat[n]=true,cnt[n]++;
    L(i,n) cnt[i]+=cnt[i+1];
    int ns=0;
    R(i,n+1) ns+=mat[i];
    cout<<ns<<'\n';
    R(i,n+1)if(mat[i]) cout<<i<<" "<<cnt[i]<<'\n';
    return 0;
}

CF126B Password

CF126B Password


同样标记可能的 border 后缀长度,然后对中间的 \(ze(i)\) 取个最大值。

找到小于等于最大值但是最大可能的下标即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int N=1e6;
int n; 
bool mat[N];
string str;

//Zebra
int ze[N];
void ze_init(){
    int l=0;
    R(i,n)if(i){
        if(l+ze[l]>i) ze[i]=min(l+ze[l]-i,ze[i-l]);
        while(i+ze[i]<n&&str[ze[i]]==str[i+ze[i]]) ze[i]++;
        if(i+ze[i]>l+ze[l]) l=i;
    }
}

//Main
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>str,n=sz(str),ze_init();
    // R(i,n) cout<<ze[i]<<' '; cout<<'\n';
    int lcp=0,id=-1;
    R(i,n)if(i){
        if(i+ze[i]==n){
            mat[ze[i]]=true;
            if(ze[i]-1>lcp) lcp=ze[i]-1,id=i;
        } else if(ze[i]>lcp) lcp=ze[i],id=i;
    }
    L(i,lcp+1)if(mat[i]){
        for(int j=id;j<id+i;j++) cout<<str[j];
        cout<<'\n',exit(0);
    }
    cout<<"Just a legend\n";
    return 0;
}

\[\Huge\rm George1123\ is\ very\ no. \]

posted @ 2020-12-03 15:52  George1123  阅读(7)  评论(0编辑  收藏  举报