上决╇ф的遗言-后缀数组

https://www.oj.swust.edu.cn/problem/show/2779

题意中文题不说了。

做法:后缀数组,想把两个串连接起来,求sa和height数组,因为题目要求求的公共子串,而且每一个串只出现一次,所以标记每一个后缀属于哪一个串,遍历heigh数组,然后判断周围有没有height值大于等于当前下标的,如果没有则这个串的是可以取得,

但不过,直接去这个串是不行的,所以应该是 max(height[i-1],height[i+1])+1这样才能取到最小值。

上决╇ф大佬的做法就不怎么看的懂了

将两个串用#连接,求后缀数组以及height数组

枚举每一个前缀 ,维护这个往前和往后第一个和这个前缀的起点不在同一个串中的位置,以及第一个和这个前缀的起点在同一个串中的位置。

定义一个函数f(i),为后缀i的一个最短前缀,满足这个字串只在该串中出现了一次,可以往前往后和本串中的后缀求最长公共前缀,然后取f(i)=max(heigth)+1

枚举每一个后缀i,他前面第一个和他不再同一个串中的后缀j,他后面第一个和他不再同一个串中的后缀k。求出ij的最长公共前缀长度x,求出ik的最长公共前传y。根据f(i),f(j),f(k)x,y来共同确定时候在这个位置有答案。并维护答案的最小值

我觉得上面的有第二个地方应该是后缀,,,只是我觉得啊。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int sa[N],height[N],c[N],x[N],t1[N],t2[N],n,s[N];
int dmin[N][20],rk[N];

void get_sa(int m)
{
    int *x=t1,*y=t2;
    for(int i=0;i<m;i++) c[i]=0;
    for(int i=0;i<n;i++) c[x[i]=s[i]]++;
    for(int i=1;i<m;i++) c[i]+=c[i-1];
    for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    for(int k=1;k<=n;k<<=1)
    {
        int p=0;
        for(int i=n-k;i<n;i++) y[p++]=i;
        for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
        for(int i=0;i<m;i++) c[i]=0;
        for(int i=0;i<n;i++) c[x[y[i]]]++;
        for(int i=1;i<m;i++) c[i]+=c[i-1];
        for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(int i=1;i<n;i++)
            x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
        if(p>=n) break;
        m=p;
    }
}
void get_height()
{
    for(int i=0;i<n;i++) rk[sa[i]]=i;
    for(int i=0,k=0;i<n;i++)
    {
        if(rk[i])
        {
            if(k) k--;
            int j=sa[rk[i]-1];
            while(s[i+k]==s[j+k]) k++;
            height[rk[i]]=k;
        }
    }
}
char str1[N],str2[N];
int vis[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>str1>>str2; n=0;
    int l1=strlen(str1);
    for(int i=0;i<l1;i++) {
        s[n++]=str1[i]-'a'+1;
        vis[n-1]=1;
    }
    s[n++]=30;
    int l2=strlen(str2);
    for(int i=0;i<l2;i++) {
        s[n++]=str2[i]-'a'+1;
        vis[n-1]=2;
    }
    s[n++]=0;
    get_sa(31);
    get_height();
    int ans=N;
    for(int i=1;i<=n;i++)
    {
        if(vis[sa[i]]+vis[sa[i-1]]==3)
        {
            if(height[i-1]<height[i]&&height[i+1]<height[i])
                ans=min(ans,max(height[i-1],height[i+1])+1);
        }
    }
    if(ans==N) ans=-1;
    cout<<ans<<endl;
    return 0;
}

上决大佬的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int sa[N],height[N],c[N],x[N],t1[N],t2[N],n,s[N];
int dmin[N][20],rk[N];

void get_sa(int m)
{
    int *x=t1,*y=t2;
    for(int i=0;i<m;i++) c[i]=0;
    for(int i=0;i<n;i++) c[x[i]=s[i]]++;
    for(int i=1;i<m;i++) c[i]+=c[i-1];
    for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    for(int k=1;k<=n;k<<=1)
    {
        int p=0;
        for(int i=n-k;i<n;i++) y[p++]=i;
        for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
        for(int i=0;i<m;i++) c[i]=0;
        for(int i=0;i<n;i++) c[x[y[i]]]++;
        for(int i=1;i<m;i++) c[i]+=c[i-1];
        for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(int i=1;i<n;i++)
            x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
        if(p>=n) break;
        m=p;
    }
}
void get_height()
{
    for(int i=0;i<n;i++) rk[sa[i]]=i;
    for(int i=0,k=0;i<n;i++)
    {
        if(rk[i])
        {
            if(k) k--;
            int j=sa[rk[i]-1];
            while(s[i+k]==s[j+k]) k++;
            height[rk[i]]=k;
        }
    }
}
void initMin()
{
    for(int i=1;i<=n;i++)
        dmin[i][0]=height[i];
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            dmin[i][j]=min(dmin[i][j-1],dmin[i+(1<<(j-1))][j-1]);
}
int RMQ(int L,int R)
{
    int k=0;
    while(1<<(k+1)<=R-L+1) k++;
    return min(dmin[L][k],dmin[R-(1<<k)+1][k]);
}
int LCP(int i,int j)
{
    int L=rk[i],R=rk[j];
    if(L>R) swap(L,R);
    L++;
    return RMQ(L,R);
}
int nxt[N][2],pre[N][2];
int super;
int getT(int pos)
{
    if(pos==0||pos==n-1||sa[pos]==super)
        return 2;
    pos=sa[pos];
    return pos>super;
}
int getlen(int pos)
{
    pos=sa[pos];
    if(pos<super)
        return super-pos;
    return n-pos-1;
}
int getminlen(int pos)
{
    int tt=getT(pos);
    int prepos=nxt[pos][tt];
    int nxtpos=pre[pos][tt];
    int maxlen=getlen(pos);
    int minlen=0;
    if(prepos!=0) minlen=max(minlen,LCP(sa[prepos],sa[pos]));
    if(nxtpos!=n-1) minlen=max(minlen,LCP(sa[pos],sa[nxtpos]));
    minlen++;
    if(minlen>maxlen) return -1;
    return minlen;
}
char str1[N],str2[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>str1>>str2; n=0;
    int l1=strlen(str1);
    for(int i=0;i<l1;i++) s[n++]=str1[i]-'a'+1;
    s[n++]=30;
    int l2=strlen(str2);
    for(int i=0;i<l2;i++) s[n++]=str2[i]-'a'+1;
    s[n++]=0;
    get_sa(31);
    get_height();
    initMin();
    super=l1;
    int last[2]={0};
    for(int i=0;i<n;i++)
    {
        pre[i][0]=last[0];
        pre[i][1]=last[1];
        int t=getT(i);
        if(t!=2) last[t]=i;
    }
    last[0]=last[1]=n-1;
    for(int i=n-1;i>=0;i--)
    {
        nxt[i][0]=last[0];
        nxt[i][1]=last[1];
        int t=getT(i);
        if(t!=2) last[t]=i;
    }
    int ans=N;
    for(int i=1;i<n;i++)
    {
        int t=getT(i);
        if(t==2) continue;
        int t_pos=pre[i][t^1];
        ///cout<<i<<" "<<t_pos<<endl;
        if(t_pos==0) continue;
        int t_minlen=getminlen(t_pos);
        if(t_minlen==-1) continue;
        int c_minlen=getminlen(i);
        if(c_minlen==-1) continue;
        ///cout<<i<<" "<<t_pos<<endl;
        int max_len=LCP(sa[i],sa[t_pos]);
        int min_len=max(t_minlen,c_minlen);
        ///cout<<min_len<<" "<<max_len<<endl;
        if(min_len>max_len) continue;
        ans=min(ans,min_len);
    }
    if(ans==N) cout<<"-1"<<endl;
    else cout<<ans<<endl;
    return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
易语言提供了很多函数和方法来获取表情的UTF-8编码。UTF-8是一种常用的字符编码方式,用来表示各种语言的字符和符号。在易语言中,我们可以使用一些内置函数来处理和获取表情的UTF-8编码。 首先,我们可以使用“变量”) функци来声明一个变量来存储表情的UTF-8编码。例如,可以声明一个字符串类型的变量“emoji”,用来存储表情的编码。 然后,我们可以使用“输入表情代码”)函数来获取用户输入的表情的UTF-8编码。这个函数会打开一个对话框,让用户输入表情代码。用户可以输入一些特殊的字符来表示表情,如“\u{1F602}”来表示一个笑脸表情。函数会将用户输入的表情代码作为字符串返回给我们。 接下来,我们可以使用“输出表情”)函数来将表情的UTF-8编码转换成实际的表情符号,并将其显示在屏幕上。这个函数需要接受一个参数,也就是表情的UTF-8编码,然后将其转换成可显示的字符串,并输出到屏幕上。 最后,我们可以使用“获取")函数来获取已经赋值给变量的表情的UTF-8编码。这个函数需要接受一个参数,也就是我们之前声明的变量名,然后会返回该变量中存储的表情的UTF-8编码。 总之,易语言提供了一系列函数来帮助我们获取表情的UTF-8编码,并进行相关操作。通过这些函数,我们可以轻松地获取和处理表情的编码,并将其显示在屏幕上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值